docs(quick-261105-din): fix 32.1 CR-01, consent allow serialized with revoke
This commit is contained in:
@@ -5,7 +5,7 @@ titles: json
|
||||
findings:
|
||||
- id: CR-01
|
||||
severity: critical
|
||||
disposition: open
|
||||
disposition: fixed
|
||||
title: "An in-flight MCP allow recreates a consent the user just revoked"
|
||||
- id: WR-01
|
||||
severity: warning
|
||||
@@ -31,7 +31,7 @@ findings:
|
||||
severity: warning
|
||||
disposition: open
|
||||
title: "`/connect` can allow a stale request after `?request=` changes"
|
||||
open: 7
|
||||
open: 6
|
||||
total: 7
|
||||
recorded: 2026-10-28T16:03:08.042Z
|
||||
---
|
||||
@@ -40,7 +40,7 @@ recorded: 2026-10-28T16:03:08.042Z
|
||||
|
||||
| Finding | Severity | Disposition | Source |
|
||||
|---------|----------|-------------|--------|
|
||||
| CR-01 | critical | open | - |
|
||||
| CR-01 | critical | fixed | sm-oauthserver-plugin 21f5985 (unreleased; ships with the next plugin tag) |
|
||||
| WR-01 | warning | open | - |
|
||||
| WR-02 | warning | open | - |
|
||||
| WR-03 | warning | open | - |
|
||||
|
||||
@@ -39,8 +39,8 @@ created: "2026-11-05"
|
||||
| T-32.1-03 | Spoofing | wristband Authorize redirect | high | mitigate | 63d05e8 touched only `allowedAuthorizeScopes`; authorize.go order: client lookup :62-82, exact redirect :84-88, PKCE :95-108, scope parse :110 | closed |
|
||||
| T-32.1-04 | Information disclosure | pact.MCPCall.Subject.TokenID | medium | mitigate | TokenID rule in pact/README.md:170, pier/README.md:13 and docs; dispatch.go:211-215 adds no log line; subject from `id.subjectFor` :172; audit.go unchanged | closed |
|
||||
| T-32.1-05 | Elevation of privilege | MCPUserGuard Implies helper | high | mitigate | U/classes/mcp_guard.go:160-175 `mcpEffectiveScopes`: personal tokens unchanged, clone only, read/write Implies only, exact stock scope required, no write-back; both call sites (:94, :145); `CompileAPITokenScopes` rejects backend/offline_access and bad Implies (api_token_scopes.go:139,:148). Residual: WR-01, WR-02 | closed |
|
||||
| T-32.1-06 | Elevation of privilege | MCP consent upsert | high | mitigate | O/controllers/mcp_consent_api.go: deny → `DenyPending` (:180-183); silent re-grant → `TouchConsent` (:355-358); decision → `replaceMCPConsent` ON CONFLICT sets scopes (:382-389), replace not union. Test `TestMCPConsentReplace`. Residual: CR-01, WR-03, WR-04 | closed |
|
||||
| T-32.1-07 | Elevation of privilege | authorizations.revoke | high | mitigate | O/controllers/authorizations.go:137-163: `LockUserGrants` advisory lock in-tx before deletes of consent, codes and tokens; `MCPSubjectRevoked` after commit. Test `TestMCPRevokeDeletesCode`. Closed at L1 only — see CR-01 | closed |
|
||||
| T-32.1-06 | Elevation of privilege | MCP consent upsert | high | mitigate | O/controllers/mcp_consent_api.go: deny → `DenyPending` (:180-183); silent re-grant → `TouchConsent` (:355-358); decision → `replaceMCPConsent` ON CONFLICT sets scopes (:382-389), replace not union. Test `TestMCPConsentReplace`. Residual: WR-03, WR-04 (CR-01 fixed in 21f5985) | closed |
|
||||
| T-32.1-07 | Elevation of privilege | authorizations.revoke | high | mitigate | O/controllers/authorizations.go:137-163: `LockUserGrants` advisory lock in-tx before deletes of consent, codes and tokens; `MCPSubjectRevoked` after commit. Test `TestMCPRevokeDeletesCode`. CR-01 fixed in 21f5985: the MCP allow takes the same lock | closed |
|
||||
| T-32.1-08 | Information disclosure | PendingRequest / IssueCode | high | mitigate | F/modules/wristband/consent.go:139-174 `lookupOwnedPending` unchanged, all misses → `ErrPendingNotFound` → 404. Plugin's `mcpPendingClientID` (mcp_consent_api.go:322-332) looks up by request id alone but both callers run it after the owner-checked `PendingRequest` | closed |
|
||||
| T-32.1-09 | Tampering | grantedScopes when scopes is absent | medium | mitigate | mcp_consent_api.go:247-250 absent scopes = requested set; offline override only when present (:224-226); request struct takes decision, scopes, backend_admin only | closed |
|
||||
| T-32.1-10 | Information disclosure | consent and revoke logs | medium | mitigate | phase diff `df2eddd..a7743e7` adds no log line in plugin non-test code; error-code sets unchanged | closed |
|
||||
@@ -68,11 +68,11 @@ created: "2026-11-05"
|
||||
|
||||
## Residual Risk (open review findings, outside the L1 register)
|
||||
|
||||
`32.1-REVIEW-DISPOSITION.md` lists these as `open`. The auditor confirmed each is still present in the code on 2026-11-05. They do not count toward `threats_open` at ASVS L1, but CR-01 would make T-32.1-07 a blocking open threat at L2.
|
||||
`32.1-REVIEW-DISPOSITION.md` lists these as `open`. The auditor confirmed each is still present in the code on 2026-11-05. They do not count toward `threats_open` at ASVS L1, but CR-01 would make T-32.1-07 a blocking open threat at L2. CR-01 has since been fixed (sm-oauthserver-plugin 21f5985).
|
||||
|
||||
| Finding | Severity | Touches | Gap |
|
||||
|---------|----------|---------|-----|
|
||||
| CR-01 | critical | T-32.1-07, T-32.1-06 | `srv.IssueCode` commits `MarkIssued` in its own transaction; `recordMCPConsent`/`replaceMCPConsent` then write the consent without `LockUserGrants` (O/controllers/mcp_consent_api.go:228-240). A revoke landing between the two is undone: the consent is re-inserted and the next authorize auto-allows. |
|
||||
| CR-01 | critical | T-32.1-07, T-32.1-06 | Fixed in sm-oauthserver-plugin 21f5985 (2026-11-05, unreleased): `MCPConsentDecide` issues the code and writes the consent in one transaction under `classes.WithinUserGrantsLock` (exclusive `LockUserGrants`, the lock revoke takes); a failed consent write rolls the code back. Tests `TestMCPConsentAllowSerializesWithRevoke`, `TestMCPConsentFailureRollsBackCode`. |
|
||||
| WR-01, WR-02 | warning | T-32.1-05 | `mcpEffectiveScopes` re-implies a declared scope the user cleared on /connect while read/write remains, and does not intersect the catalog with `golem15.oauthserver.mcp_scopes`. |
|
||||
| WR-04 | warning | T-32.1-06 | narrowing a consent does not revoke refresh tokens carrying the removed scopes or offline_access. |
|
||||
| WR-03 | warning | T-32.1-06 | the consent backfill seeds from tokens the verifier would refuse (nil-expiry, inactive/revoked clients, rotated refresh tokens). |
|
||||
@@ -94,6 +94,6 @@ created: "2026-11-05"
|
||||
- [x] Accepted risks documented in Accepted Risks Log
|
||||
- [x] `threats_open: 0` confirmed
|
||||
- [x] `status: verified` set in frontmatter
|
||||
- [ ] CR-01 given a disposition in 32.1-REVIEW-DISPOSITION.md (fix or accept)
|
||||
- [x] CR-01 given a disposition in 32.1-REVIEW-DISPOSITION.md (fixed: sm-oauthserver-plugin 21f5985)
|
||||
|
||||
**Approval:** verified 2026-11-05 (ASVS L1; CR-01 outstanding)
|
||||
**Approval:** verified 2026-11-05 (ASVS L1; CR-01 fixed in sm-oauthserver-plugin 21f5985, unreleased)
|
||||
|
||||
Reference in New Issue
Block a user