Problem
The JWT signing secret defaults to a publicly-known constant and is only hard-rejected in HOSTED deployment mode. The default deployment mode is self_hosted, so a server started without AUTH_SECRET signs all JWTs with "CHANGE-ME-IN-PRODUCTION" and merely logs a warning.
Because auth is ON by default (CODEFRAME_AUTH_REQUIRED defaults true) and HS256 is used, anyone who knows the project can forge a valid JWT for any user_id, fully bypassing auth on all 22 v2 routers plus the WS/SSE routes (which decode with the same secret).
Evidence
codeframe/auth/manager.py:21-22 — SECRET = os.getenv("AUTH_SECRET", DEFAULT_SECRET), DEFAULT_SECRET = "CHANGE-ME-IN-PRODUCTION"
codeframe/ui/server.py:68-127 — _validate_security_config() hard-fails on the default secret only when deployment mode is HOSTED (server.py:114); the default self_hosted path just logs a warning (server.py:122-125) and continues.
Fix
- Fail hard (raise
RuntimeError, refuse to start) whenever auth is enabled (auth_required() is true) and SECRET == DEFAULT_SECRET, regardless of deployment mode.
- Provide an explicit escape hatch for local dev only (e.g.
CODEFRAME_ALLOW_INSECURE_SECRET=1) if a no-secret quickstart is desired.
- Document
AUTH_SECRET as mandatory in docs/QUICKSTART.md.
Acceptance criteria
Source: release-readiness audit 2026-06-13 (security agent, finding H1).
Problem
The JWT signing secret defaults to a publicly-known constant and is only hard-rejected in
HOSTEDdeployment mode. The default deployment mode isself_hosted, so a server started withoutAUTH_SECRETsigns all JWTs with"CHANGE-ME-IN-PRODUCTION"and merely logs a warning.Because auth is ON by default (
CODEFRAME_AUTH_REQUIREDdefaults true) and HS256 is used, anyone who knows the project can forge a valid JWT for anyuser_id, fully bypassing auth on all 22 v2 routers plus the WS/SSE routes (which decode with the same secret).Evidence
codeframe/auth/manager.py:21-22—SECRET = os.getenv("AUTH_SECRET", DEFAULT_SECRET),DEFAULT_SECRET = "CHANGE-ME-IN-PRODUCTION"codeframe/ui/server.py:68-127—_validate_security_config()hard-fails on the default secret only when deployment mode isHOSTED(server.py:114); the defaultself_hostedpath just logs a warning (server.py:122-125) and continues.Fix
RuntimeError, refuse to start) whenever auth is enabled (auth_required()is true) andSECRET == DEFAULT_SECRET, regardless of deployment mode.CODEFRAME_ALLOW_INSECURE_SECRET=1) if a no-secret quickstart is desired.AUTH_SECRETas mandatory indocs/QUICKSTART.md.Acceptance criteria
AUTH_SECRETraises a clear startup error (not a warning).AUTH_SECRET.Source: release-readiness audit 2026-06-13 (security agent, finding H1).