You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#2845 populated application.wheels.protectedControllerMethods so framework helpers (env, model, filterChain, ...) can't be invoked as actions. Its PR body states the intent: "Reaching one of these names now throws Wheels.ActionNotAllowed and falls through to the missing-action / 404 path, matching every other non-existent action." CLAUDE.md Anti-Pattern 8 repeats it ("→ 404").
The block itself works — the helper never dispatches, on every engine, and private methods are correctly unreachable (probed both directions). Only the status contract is broken: ActionNotAllowed surfaces as 500 while a plain missing action 404s.
A 500 miscategorizes probe traffic in monitoring and tells URL scanners they found something, where a 404 would not.
Root cause
vendor/wheels/controller/processing.cfc:136-144 — $callAction() throws raw Wheels.ActionNotAllowed (verified at source: line 138 gate, line 140 throw).
vendor/wheels/events/EventMethods.cfc:83-90 — only ^Wheels\.[A-Za-z]*NotFound$ maps to 404; everything else falls to the 500 branch.
Reproducer caveat: make sure no .resources(name="posts") route precedes the wildcard, or /posts/env matches the resource show route with key="env" and you'll observe verifies/binding behavior instead.
Reported by the guide-behavioral-audit P1 batch 2 (work item p1-9-authz, claim authz-helper-named-action-blocked; live on Lucee 7 + Adobe 2023, dev + prod; root cause re-verified at source by the consolidator).
Summary
#2845 populated
application.wheels.protectedControllerMethodsso framework helpers (env,model,filterChain, ...) can't be invoked as actions. Its PR body states the intent: "Reaching one of these names now throwsWheels.ActionNotAllowedand falls through to the missing-action / 404 path, matching every other non-existent action." CLAUDE.md Anti-Pattern 8 repeats it ("→ 404").The block itself works — the helper never dispatches, on every engine, and private methods are correctly unreachable (probed both directions). Only the status contract is broken: ActionNotAllowed surfaces as 500 while a plain missing action 404s.
GET /bare/env(helper name)GET /bare/notreal(missing action)A 500 miscategorizes probe traffic in monitoring and tells URL scanners they found something, where a 404 would not.
Root cause
vendor/wheels/controller/processing.cfc:136-144—$callAction()throws rawWheels.ActionNotAllowed(verified at source: line 138 gate, line 140 throw).vendor/wheels/events/EventMethods.cfc:83-90— only^Wheels\.[A-Za-z]*NotFound$maps to 404; everything else falls to the 500 branch.Proposed direction (either)
$throwErrorOrShow404Page(type="Wheels.ActionNotAllowed", ...)in$callAction()(mirrors RecordNotFound handling, gives the production 404 page) — matches fix(controller): populate protectedControllerMethods so global helpers aren't URL-invokable #2845's wording most closely; orActionNotAllowedto the 404 mapping in EventMethods.cfc (ReFindNoCase("^Wheels\.([A-Za-z]*NotFound|ActionNotAllowed)$", ...)).Update CLAUDE.md Anti-Pattern 8 whichever way this resolves (it currently states "→ 404", which is wrong today).
Acceptance
protectedMethodsSpec.cfcextended to assert the HTTP status, not just the throw).Reproducer caveat: make sure no
.resources(name="posts")route precedes the wildcard, or/posts/envmatches the resourceshowroute withkey="env"and you'll observe verifies/binding behavior instead.Reported by the guide-behavioral-audit P1 batch 2 (work item p1-9-authz, claim authz-helper-named-action-blocked; live on Lucee 7 + Adobe 2023, dev + prod; root cause re-verified at source by the consolidator).