ScopeCreep — OAuth Scope Audit
32 OAuth grants across 14 SaaS apps. For every grant: scopes granted vs scopes actually used in last 90 days, classification (active / dormant / unused), recommended minimum-grant. Flags the dormant 'admin: *', the 'iam:*' that has never been used, and the former-employee Google Workspace token still alive.
What it is
The shape behind least-privilege OAuth hygiene (Spectral, SaaS-security tools, AWS Access Analyzer). Every grant on one screen. Granted vs used. The gap is the audit finding.
What’s in it
- 32 grants across 14 apps — GitHub Apps, Slack Apps, Salesforce Connected Apps, HubSpot Private Apps, Stripe Restricted Keys, AWS IAM Roles, Okta M2M, 1Password Service Accounts, Datadog API keys, Sentry integrations, Notion + Linear + Figma + PagerDuty.
- Each scope tagged with criticality (low/medium/high/critical) + 90-day usage telemetry. Classified as active / dormant / unused.
- Worst-offender findings:
ci-deploy-bot—workflows:write+administration:writenever used in 90 dayskyc-checker—admin.directory.user.readonlydormant 880 daysdata-sync(Salesforce) —fullscope granted, 0 usesiam-ci-role(AWS) —iam:*granted, never invokedformer-employee-token— dormant 240 days, gmail+drive readonly, never revokedunknown-iam-user-2022—AdministratorAccess, never used, no owner
- Minimum-grant YAML preview — for every grant, the proposed least-privilege grant with the over-permissioned scopes commented out.
Why this shape
SOC2 CC6.3 (least privilege), NIST 800-53 AC-6, OAuth 2.1 §2.5 (minimum scope), CIS Controls v8 §6.1 — every framework’s hardest finding is the same: dormant high-privilege scopes. The fix is mechanical (drop the scope, redeploy), but it requires the visibility first. ScopeCreep prototypes that visibility.
How it ships
Single HTML file, ~22KB. Zero dependencies. 32 grants × per-scope usage classification + recommended-grant generator in 240 lines of vanilla JavaScript.