Skip to content

fix(config): require non-empty reload password for environment switching - #2082

Merged
bpamiri merged 1 commit into
developfrom
peter/fix-empty-reload-password
Apr 10, 2026
Merged

bpamiri merged 1 commit into
developfrom
peter/fix-empty-reload-password

Conversation

@bpamiri

@bpamiri bpamiri commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Removes the !Len(application.$wheels.reloadPassword) branch that allowed unauthenticated environment switching when reloadPassword was empty
  • Now requires a non-empty reloadPassword AND a matching URL password parameter for environment switching to succeed
  • Adds a startup warning log entry when reloadPassword is empty, informing that URL-based reload is disabled

Test plan

  • New ReloadPasswordSpec.cfc verifies empty password blocks reload, correct password allows reload, wrong password rejects reload, and MessageDigest.isEqual is used for constant-time comparison
  • Full test suite passes (2672 pass, 0 fail, 0 error)
  • Security test suite passes

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@bpamiri
bpamiri merged commit ecf419f into develop Apr 10, 2026
3 checks passed
@bpamiri
bpamiri deleted the peter/fix-empty-reload-password branch April 10, 2026 09:37
@bpamiri bpamiri mentioned this pull request Apr 16, 2026
5 of 7 tasks
bpamiri added a commit that referenced this pull request Jun 12, 2026
…imit warm-path attempts (#3140)

* fix(cli): app template reload gate fails closed and logs warm-path attempts

Mirror of the #3062 hardening in the scaffolded app's public/Application.cfc:
an empty or missing reloadPassword now disables ?reload= entirely (the gate
requires a non-empty configured password plus a matching password parameter),
wrong-password attempts against a warm application are logged to
wheels_security.log with the trusted client IP, and failed attempts feed the
same 5-failures-in-5-minutes per-IP rate limit as the cold-start path.

Refs #3062

Signed-off-by: Peter Amiri <peter@alurium.com>

* fix(public): empty reloadPassword disables URL reload; warm-path attempts logged and rate-limited

The onRequestStart reload gate fired whenever the configured reloadPassword
was EMPTY (!Len on the allow side of the disjunction), so any anonymous
client could ?reload=true a warm app into an applicationStop() restart loop
— while the framework's own boot warning claimed the opposite. Wrong-password
attempts against a warm app were served normally with no wheels_security.log
entry and no rate-limit count: all the #2082 hardening lived only in the
cold-start path (vendor/wheels/events/onapplicationstart.cfc).

The gate now FAILS CLOSED in all four same-lineage public/Application.cfc
copies (repo demo app, starter-app and tweet examples; the CLI app template
lands in the preceding commit): a reload requires a non-empty configured
password AND a matching password parameter, mirroring the environment-switch
leg and making the boot warning true. Warm-path wrong-password attempts are
logged with the trusted client IP and feed the same per-IP
application.$reloadRateLimit bucket as the cold-start path (5 failures in
5 minutes locks the source out, correct password included). The examples
copies also upgrade from CFML's case-insensitive == to $secureCompare().

ReloadPasswordGateParitySpec pins the contract structurally across all four
copies (runtime exercise would applicationStop() the suite mid-run).

Harness/CI flows that leaned on the open gate are fixed in the same change:
tools/docker/*/settings.cfm now ship reloadPassword="wheels-dev" (smoke-env.yml
drops its sed and just guards against drift), and tools/test-local.sh +
tools/test-cli-local.sh send wheels-dev instead of the mismatched "wheels".
Guides (security-hardening, production-config, debug-panel, caching, i18n)
updated to describe the fixed contract.

Fixes #3062

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

---------

Signed-off-by: Peter Amiri <peter@alurium.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
bpamiri added a commit that referenced this pull request Jun 13, 2026
…g can work (#3141)

Since #2082 the ?reload=<environment> switch requires a non-empty
reloadPassword plus a matching password parameter (and is gated by
allowEnvironmentSwitchViaUrl), but the debug bar still rendered the
Testing/Maintenance/Production quick-switch anchors only when NO
reloadPassword was set — the exact configuration where switching is
impossible. Clicking one restarted the app and silently stayed in the
current environment.

The Environment panel now renders the links only when a reloadPassword
is configured AND allowEnvironmentSwitchViaUrl resolves true. The links
never embed the password: a new wdbEnvSwitch() handler prompts for it
at click time and issues the documented
?reload=<environment>&password=... request. The plain ?reload=true
reload anchor keeps its existing no-password gate.

Guides (debug-panel.mdx, environments-and-configuration.mdx) updated to
describe the working behavior instead of the dead-link caveat.

Fixes #3060

Signed-off-by: Peter Amiri <peter@alurium.com>
Signed-off-by: Peter Amiri <petera@pai.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Amiri <petera@pai.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant