Files
summercms/.planning/phases/08-oauth2-1-authorization-server/08-SECURITY.md

6.8 KiB

phase, slug, status, threats_open, threats_total, threats_closed, accepted_risks, asvs_level, block_on, register_authored_at_plan_time, created
phase slug status threats_open threats_total threats_closed accepted_risks asvs_level block_on register_authored_at_plan_time created
08 oauth2-1-authorization-server verified 0 11 11 0 1 high true 2026-10-12

Phase 08 — Security

Per-phase security contract: threat register, accepted risks, and audit trail.

Detailed per-threat findings and named test evidence live in 08-SECURITY-REVIEW.md (2026-09-24, performed by the 08-10 executor, not an independent auditor; see its Reviewer Note). This file is the gate contract derived from all ten <threat_model> blocks. The plans carry no severity column; severities below are assigned at this audit. Framework paths are relative to summercms.go/modules/; app paths are relative to fonoteka.go/plugins/golem15/fonoteka/.


Trust Boundaries

Boundary Description Data Crossing
connector → raw /.well-known and /oauth/mcp/* routes untrusted discovery, authorize, register and token traffic on raw (unguarded) routes client metadata, redirect URIs, PKCE challenge/verifier, client secret (high)
validated redirect → Location client-controlled redirect trusted only after exact allow-list match code, state, error (high)
wristband records → GORM app-agnostic code/refresh/client state persisted with row locks code hash, refresh hash, lineage (high)
browser JWT principal → consent / connected-app API authenticated user ids cross ownership, scope and collection boundaries request handle, scopes, token ids (high)
refresh credential → token endpoint long-lived bearer-like credential requests a new grant branch refresh token (high)
transaction outcome → OAuth error lineage revocation must commit although the response is invalid_grant revocation state
operator CLI → client store trusted input creates a recoverable-once confidential client client secret (high)
bearer header → personal-token /me untrusted bearer crosses existing token and scope guards user profile fields (medium)
PHP capture → committed fixtures; gate → child processes live credentials must become placeholders before git; secrets cross shell/Node/Go credentials (high)

Threat Register

Threat ID Category Component Severity Disposition Mitigation Status
T-08-PKCE Spoofing/Elevation authorize / token exchange high mitigate wristband/authorize.go:77 requires code_challenge_method=S256, rejects missing challenge (:84); verifier compared through wristband/crypto.go:34 subtle.ConstantTimeCompare closed
T-08-CODE-REPLAY Spoofing auth-code store / exchange high mitigate classes/auth/oauth_store.go:130 ByCodeHashForUpdate (clause.Locking UPDATE) inside the single transaction at :45; concurrent one-winner tests per 08-SECURITY-REVIEW closed
T-08-REFRESH-REPLAY Spoofing/Elevation refresh state machine high mitigate oauth_store.go:199 ByTokenHashForUpdate, :243 RevokeLineage (locked walk); lineage kill committed before invalid_grant; manual-token-delete cascade fixed in 08-10 (controllers/api/token_api_controller.go Destroy) closed
T-08-OPEN-REDIRECT Spoofing/Disclosure authorize high mitigate wristband/authorize.go:62 exact stringSliceContains(client.RedirectURIs, …) check precedes every authorizeErrorRedirect closed
T-08-SCOPE-CEILING Elevation authorize / consent / refresh / CLI high mitigate requested ∩ ScopeCeiling (wristband/stores.go:29) before persistence; consent four-way intersection app-owned (wristband/consent.go:8, D-08); refresh copies stored scopes only closed
T-08-CROSS-USER Elevation consent / connected apps high mitigate controllers/api/connected_app_controller.go:28,75 scope reads/deletes to user_id = ?; missing/foreign/manual ids return identical 404 Token not found (:70,:78) closed
T-08-SURFACE Elevation route groups / MCP boundary high mitigate raw OAuth routes vs JWT management routes proven by routes_isolation_test.go:TestFullRouteTableAuthGroupMutualExclusivity, TestOAuthTokenSurfaceIsolationCoverage, TestOAuthMetadataRouteIsolation closed
T-08-REQUEST-LEAK Information Disclosure metadata / logs / fixtures / output high mitigate opaque pending-request handle (wristband/authorize.go:29); positive allow-list serializers (TestOAuthConsentShowExactKeySet); no fmt.Print*/log.*/slog.* on secrets; check-phase8.sh redact_phase8 + stage_secret_scan closed
T-08-SECRET-TIMING Information Disclosure client auth / issued client medium mitigate single hash/compare path through wristband/crypto.go:34 subtle.ConstantTimeCompare; secret shown once by the client command closed
T-08-DCR-FLOOD Denial of Service register / client store medium mitigate wristband/register.go:67 http.MaxBytesReader at 65536 (server.go:99); DCRClientCap (server.go:50, ErrClientCapReached) under transactional cap/sweep/create; throttle:fonoteka-oauth-register 30/min per IP closed
T-08-SC Tampering dependencies low mitigate no go.mod/go.sum change in any phase 08 commit; stdlib port, no zitadel/oidc (D-01); Playwright/Node reused from existing lockfile closed

Status: open · closed · open — below high threshold (non-blocking) Severity: critical > high > medium > low — only open threats at or above workflow.security_block_on count toward threats_open Disposition: mitigate (implementation required) · accept (documented risk) · transfer (third-party)


Accepted Risks Log

No accepted risks.

Accepted risks do not resurface in future audit runs.


Security Audit Trail

Audit Date Threats Total Closed Open Run By
2026-09-24 11 11 0 08-10 executor (08-SECURITY-REVIEW.md, self-performed)
2026-10-12 11 11 0 /msd-secure-phase orchestrator (L1 grep re-check; go test -short green for modules/wristband, fonoteka classes/auth, controllers/api)

Security Audit 2026-10-12

Metric Count
Threats found 11
Closed 11
Open 0

Short-circuited at L1 (threats_open 0, register authored at plan time, ASVS 1); no auditor subagent spawned. Every mitigation above was re-located in current source rather than inherited from the 2026-09-24 review.


Sign-Off

  • All threats have a disposition (mitigate / accept / transfer)
  • Accepted risks documented in Accepted Risks Log
  • threats_open: 0 confirmed
  • status: verified set in frontmatter

Approval: verified 2026-10-12