F1 — Token-scope audit follow-up (from Epic #1565)
Three gaps where token-scope validation silently skips enforcement instead of reporting violations.
Finding 1 (HIGH) — internal/scope/validator.go:151-153
When TokenIntrospector.Introspect() returns TokenInfo.Error != nil (e.g. network failure, API error), validator appends a warning and continues — scope check is silently skipped. If a persona declares token_scopes: [repo] and introspection fails, the persona runs unvalidated.
Fix: When scope is required (not optional), emit a ScopeViolation instead of warning. The persona explicitly asked for this scope — failing to validate it should block, not warn.
// Current (line 151-153):
if tokenInfo.Error != nil {
result.Warnings = append(result.Warnings, ...)
continue
}
// Proposed: check if scope is required, emit violation instead of warning
Finding 2 (MED) — internal/scope/resolver.go:28-31
Bitbucket and unknown forge types return nil, error from Resolve() — but the error is informational ("not yet supported"), not a violation. The validator treats this as a non-blocking skip.
Fix: Return a violation with hint pointing to forge support status, not just an error that gets swallowed.
Finding 3 (MED) — internal/scope/introspect.go:102-105
Fine-grained GitHub PATs lack X-OAuth-Scopes header. Introspector sets TokenInfo.Error with a message, which feeds into Finding 1's silent-skip path. Fine-grained PATs do have permissions — they're just not readable via the headers API.
Fix: Suggest token recreation as classic PAT (scopes readable) or add a --skip-scope-check flag for fine-grained PAT users. Violation hint: "fine-grained PATs cannot be introspected; recreate as classic PAT or use --skip-scope-check".
LOW findings (document only)
internal/pipeline/executor_dispatch.go:538-553 — step-level Permissions.AllowedTools decoupled from token_scopes validation. Design choice, not a bug.
- Persona markdown frontmatter
token_scopes is ignored — manifest is source of truth. Correct by design.
F1 — Token-scope audit follow-up (from Epic #1565)
Three gaps where token-scope validation silently skips enforcement instead of reporting violations.
Finding 1 (HIGH) —
internal/scope/validator.go:151-153When
TokenIntrospector.Introspect()returnsTokenInfo.Error != nil(e.g. network failure, API error), validator appends a warning andcontinues — scope check is silently skipped. If a persona declarestoken_scopes: [repo]and introspection fails, the persona runs unvalidated.Fix: When scope is
required(notoptional), emit aScopeViolationinstead of warning. The persona explicitly asked for this scope — failing to validate it should block, not warn.Finding 2 (MED) —
internal/scope/resolver.go:28-31Bitbucket and unknown forge types return
nil, errorfromResolve()— but the error is informational ("not yet supported"), not a violation. The validator treats this as a non-blocking skip.Fix: Return a violation with hint pointing to forge support status, not just an error that gets swallowed.
Finding 3 (MED) —
internal/scope/introspect.go:102-105Fine-grained GitHub PATs lack
X-OAuth-Scopesheader. Introspector setsTokenInfo.Errorwith a message, which feeds into Finding 1's silent-skip path. Fine-grained PATs do have permissions — they're just not readable via the headers API.Fix: Suggest token recreation as classic PAT (scopes readable) or add a
--skip-scope-checkflag for fine-grained PAT users. Violation hint: "fine-grained PATs cannot be introspected; recreate as classic PAT or use --skip-scope-check".LOW findings (document only)
internal/pipeline/executor_dispatch.go:538-553— step-levelPermissions.AllowedToolsdecoupled from token_scopes validation. Design choice, not a bug.token_scopesis ignored — manifest is source of truth. Correct by design.