Skip to content

docs(web/guides): correct reload-password behavior claims in security-hardening guide - #3064

Merged
bpamiri merged 1 commit into
developfrom
peter/docs-audit-sec-hardening
Jun 12, 2026
Merged

docs(web/guides): correct reload-password behavior claims in security-hardening guide#3064
bpamiri merged 1 commit into
developfrom
peter/docs-audit-sec-hardening

Conversation

@bpamiri

@bpamiri bpamiri commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Guide behavioral audit follow-up for web/sites/guides/src/content/docs/v4-0-0/deployment/security-hardening.mdx. Each correction was live-verified against current develop (post #3036/#3037/#3038/#3057/#3058) and re-cited against today's source.

Corrections

  1. "If it's empty, both are disabled" — false. With set(reloadPassword=""), plain ?reload=true from any anonymous client still fires applicationStop() — the warm-reload gate in public/Application.cfc lines 268-288 explicitly passes when the password has no length; only the environment-switch leg (vendor/wheels/events/onapplicationstart.cfc line 188) requires a non-empty password. The guide now states that empty disables URL environment switching only, that plain reload stays open, and links the tracking issue Reload-password contract drift: empty password leaves ?reload=true open to anonymous restarts, warm-app wrong-password attempts are never logged or rate-limited, and the boot warning misstates behavior #3062 (the boot warning at onapplicationstart.cfc 371-374 repeats the same false "disabled" claim).

  2. "those URLs return 403 unless the attacker also knows the secret" — false. A missing/wrong password is served normally (HTTP 200, no reload, no 403) — the gate in public/Application.cfc lines 268-288 simply falls through to normal request serving. The only 403s on this surface are the CLI command gate in vendor/wheels/Public.cfc lines 90-111. Sentence replaced accordingly.

  3. Logging/rate-limit claim overstated + stale line cites. Rejected attempts log at vendor/wheels/events/onapplicationstart.cfc line 219, accepted at line 227, IP rate-limit (5 failures / 5 min) at lines 160-178 — the guide cited 189/197/135. More importantly, that code only runs on application cold start: a wrong-password ?reload=true against a warm app produces no wheels_security.log entry and no rate-limit count. The guide now scopes the claim and updates the cites. Boot-warning cite updated 287-290 → 371-374.

  4. CSRF line cites refreshed. $verifyAuthenticityToken() is at vendor/wheels/controller/csrf.cfc line 59 (guide said 63); $isVerifiedRequest() at line 78 (guide said 82). $runCsrfProtection() line 37 and the view-helper cites (csrfMetaTags 10, authenticityTokenField 26) were verified still correct and left unchanged.

No change needed for ?reload=production switching itself: #3058 (merged today) fixed the $location crash, so switching into production/maintenance now sticks.

Verification

  • pnpm verify:docs src/content/docs/v4-0-0/deployment/security-hardening.mdx → 11 tagged blocks, 11 passed, exit 0.

Refs #3062

🤖 Generated with Claude Code

…-hardening guide

Audit-verified corrections against current develop:
- empty reloadPassword does NOT disable plain ?reload=true (refs #3062)
- wrong password is served normally (200), not 403
- reload logging/rate-limit only fires on cold start; refresh stale line cites
- CSRF helper line cites updated ($verifyAuthenticityToken 59, $isVerifiedRequest 78)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Peter Amiri <peter@alurium.com>

@wheels-bot wheels-bot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wheels Bot — Reviewer

TL;DR: This PR corrects four false or stale claims about the reload-password contract in the security-hardening guide (empty password ≠ disabled reload, no 403 on wrong password, cold-start-only logging/rate-limiting, refreshed CSRF line cites), tracking the framework-side drift in #3062. I re-verified every line citation in the diff against current source and all of them are accurate; the behavioral claims match the gate code in public/Application.cfc and vendor/wheels/events/onapplicationstart.cfc. Verdict: comment — one minor residual docs nit below, nothing blocking.

Verified

  • public/Application.cfc:268-288 — warm-reload gate fires on !Len(application.wheels.reloadPassword) (line 273), so empty password leaves plain ?reload=true open; a set-but-wrong password fails the condition and falls through to normal serving (no 403). Matches the new lines 155 and 170 of the guide.
  • vendor/wheels/events/onapplicationstart.cfc:188 — env-switch leg requires Len(application.$wheels.reloadPassword); rate limit at 160-178 (5 failures / 5 min); rejected log at 219; accepted log at 227; boot warning at 371-374. All cited line numbers in the new text are correct, and the cold-start-only scoping caveat is accurate (the whole block lives in onapplicationstart).
  • vendor/wheels/controller/csrf.cfc$runCsrfProtection 37, $verifyAuthenticityToken 59, $isVerifiedRequest 78 ✓. vendor/wheels/view/csrf.cfccsrfMetaTags 10, authenticityTokenField 26 ✓. vendor/wheels/events/init/security.cfm:3 (csrfStore = "session") ✓.
  • "the only 403s on this surface live on the CLI command gate in vendor/wheels/Public.cfc" — confirmed at Public.cfc:90/95/106/111; no other 403 on the reload path.
  • Commit b401edbf conforms to commitlint (87-char docs(web/guides) header) and carries a matching DCO sign-off. No changelog fragment required for docs type.

Docs

  • security-hardening.mdx:157 — "accepted attempts log … (lines 219 and 227)" is slightly overgeneral. Line 227's "Reload accepted" log only fires when reloadPasswordMatched is true, and that flag is set exclusively inside the environment-switch branch (!IsBoolean(URL.reload), onapplicationstart.cfc:185-192). A correct-password plain ?reload=true that happens to arrive during a cold start instead satisfies the failed-attempt tracker at lines 208-222 (both URL keys present, reloadPasswordMatched false) — it logs "Reload password rejected" and increments the per-IP rate-limit counter. So on the only path where this logging runs at all, the "accepted" log covers environment switches only, and plain reloads can be mislabeled as rejected. Suggested tweak: scope the sentence, e.g. "rejected attempts log at line 219; accepted environment switches at line 227". The mislabeled rejected-log/rate-limit bump for correct-password boolean reloads is itself framework-bug material worth appending to #3062, since fixing it would change what the guide should say here.

Nice work overall — this is exactly the kind of live-verified docs correction the audit is for, and pointing the prose at #3062 instead of papering over the gate's behavior is the right call.

@bpamiri
bpamiri merged commit bacb9d9 into develop Jun 12, 2026
14 checks passed
@bpamiri
bpamiri deleted the peter/docs-audit-sec-hardening branch June 12, 2026 04:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant