Repository navigation
Close the database wizard's endpoints once the site is installed - #663
Conversation
POST /wizard_db and POST /test_db are registered for the life of the process and take no credentials, because during an install there is nobody to hold any. Nothing turned them off afterwards. Refuse both once the site has a database and an admin. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The change is small, focused, and correct, follows the existing middleware convention, and is backed by a passing test that exercises the installed, pre-install, and mid-install states.
Review effort: Balanced
Findings: None
What changed in this PR
This PR closes a security gap in GoBlog's install wizard. The database-step endpoints POST /wizard_db (which rewrites .env with whatever database the request names) and POST /test_db (which opens any file/host it's given) take no credentials — because during an install there is no admin to authenticate — and were previously registered for the life of the process with nothing to turn them off once the install finished. The PR adds a small installOnly middleware that returns 403 once the site is fully installed (has a database and an admin), while leaving the wizard fully functional before and during install.
Changes:
- Added a
goblog.installOnlyGin middleware that aborts with403when!_wizard.IsDbNil() && !_auth.IsWizardMode(c)(i.e. a DB exists and an admin row exists). - Wired the middleware onto
POST /wizard_dbandPOST /test_db. - Added
TestInstallOnlycovering the installed (403,.envuntouched, no file created), pre-install (303,.envwritten), and mid-install (303) states.
| File | Description |
|---|---|
goblog.go |
Adds the installOnly middleware and applies it to the two wizard database endpoints. |
wizard_install_only_test.go |
New test verifying the endpoints are blocked post-install and still work before/mid-install. |
I verified the key correctness concerns:
- Gin semantics:
installOnlynot callingc.Next()when it allows the request is correct and consistent with the existingrequireJSONmiddleware pattern (goblog.go:620-642);AbortWithStatusJSONcorrectly stops the chain when installed. - Nil safety:
IsWizardModedereferences the DB, but Go's short-circuit evaluation (!IsDbNil()first) ensures it's only called when the DB is non-nil, avoiding a panic in theapp(nil)test path. - No TOCTOU gap: installed sites always connect the DB at startup (goblog.go:271-277), so
IsDbNil()isfalsebefore any request is served. - Test soundness: all referenced symbols/fields exist (
auth.New/BlogUser/AdminUser/ProviderGitHub,wizard.New,templateWithErrors, and thedbtype/sqlite_file→sqlite_dbform/env field mapping indb.go), andt.Chdiris supported on go 1.26.
I did not find any objective issues warranting a comment.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Problem
POST /wizard_dbandPOST /test_dbbelong to the install wizard's database step. They take no credentials, because during an install there is nobody to hold any, and they are registered for the life of the process. Nothing turned them off once the install was finished.Fix
A small
installOnlymiddleware on both routes answers 403 once the site has a database and an admin. Before that (no database yet, or a database with no admin) the wizard works as before.Testing
New
TestInstallOnly: on an installed site both endpoints return 403 and.envis untouched; before install and mid-install/wizard_dbstill saves. The test fails without the guard.go test ./...passes, and the install smoke test covers the wizard path in CI.Upgrading
Sites should upgrade to the release that contains this.
🤖 Generated with Claude Code