fix(security): JWT exp, OAuth2 grant-type + constant-time secret, HttpSecurity warning (v26.06.12)#38
Merged
Merged
Conversation
…cret, HttpSecurity warning + bump v26.06.12 Surfaced by an adversarial security audit while validating implement-security (skill itself clean — enforcement proven, no silent auth bypass). Framework fixes: - JWT: decode now requires exp (options require=[exp]); encode auto-adds exp (expiration_seconds, default 3600) when absent. A no-exp token previously never expired. Same require=exp added to the JWKS resource-server validator. - OAuth2 AuthorizationServer: constant-time client-secret compare (secrets.compare_digest, was !=); enforce the client's registered grant type — an authorization_code client can no longer mint client_credentials tokens (UNAUTHORIZED_CLIENT); server-unsupported grants still UNSUPPORTED_GRANT_TYPE. - HttpSecurity.build(): warn when rules are set without a terminal any_request() rule (unmatched paths fall through allowed). Tests: tests/security/test_security_hardening.py (8) + updated the authz-server fixture (register for client_credentials) and resource-server test helper (exp). Gates: mypy --strict (607), ruff + format, full suite 3645 passed. Session-subsystem hardening (fixation id rotation, secure cookie default, Redis deserialization allowlist) + a tests/session suite tracked as a follow-up.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
An adversarial security audit run while validating the
implement-securityskill (the skill itself validated clean — enforcement proven via tests + live HTTP, no silent auth bypass) surfaced real, security-relevant framework bugs. Each was verified against source before fixing.Fixes
expnot required (token never expires).JWTService.decodeand the JWKS resource-server validator verifiedexponly when present, so a token minted with noexpwas accepted forever.decodenow requiresexp;encodeauto-addsexp(now +expiration_seconds, default 3600) when the payload omits one.!=(timing side-channel). Nowsecrets.compare_digest.authorization_grant_type, so anauthorization_codeclient could mintclient_credentialstokens. Theclient_credentialsgrant now requires the client to be registered for it (UNAUTHORIZED_CLIENT); server-unsupported grants still returnUNSUPPORTED_GRANT_TYPE.HttpSecurityfootgun.build()now warns when authorization rules are configured without a terminalany_request()rule (unmatched paths fall through allowed), recommending.any_request().deny_all()/.authenticated().Tests
tests/security/test_security_hardening.py(8): no-exp token rejected + encode auto-exp;authorization_codeclient blocked fromclient_credentials; wrong secret rejected; HttpSecurity warns without / stays quiet with a terminal rule. Updated the authz-server fixture (register forclient_credentials) and the resource-server token helper (carryexp) — both previously relied on the now-fixed behaviors.Gates
mypy --strict(607) ✓ ·ruff+ruff format✓ · full suite 3645 passed, 1 skipped.Follow-up (not in this PR)
The audit also flagged session-subsystem issues — session-fixation (no id rotation on login),
securecookie defaulting off, and a Redis-deserialization gadget — in a subsystem with notests/sessionsuite. Because those changes touch untested auth-adjacent code, they're deliberately deferred to a dedicated, properly-tested session-hardening release rather than bolted on here.Bumps
v26.06.11 → v26.06.12, CHANGELOG,uv.locksynced.