Skip to content
FeaturesPricingAffiliateBlogHelpAboutContact
Get StartedSign In
Back to Blog
industry2026-05-2312 min read

My OAuth refresh with broader scope was accepted — RFC 6749 §6 violation (PR #644 V F2)

Mart (31) freelance software developer in Tallinn Old Town runs a small studio building bespoke restaurant analytics dashboards. Built one for friend Karl s Kasi-Kohvik specialty café on Raekoja Plats with scope=orders.read read-only. 3 months later Karl wanted "mark as paid" feature requiring orders.write. Mart tested: refresh request with scope=orders.read orders.write. Per RFC 6749 §6 must be rejected (refresh scope MUST NOT include any scope not originally granted). thMenu access-token endpoint accepted, 200 OK new token, token covered orders.write too. PATCH /api/orders/[id]/status succeeded. Privilege escalation vector. Mart responsible-disclosed via security@thmenu.com (used test client, not Karl s production token). thMenu support shipped fix 5 days later + no formal bug-bounty program but 1-year free Pro tier upgrade for Mart s studio + Hall of Fame mention. Forensic: apps/web-admin/src/app/api/oauth/token/route.ts refresh-token branch. `scope: body.scope ?? tokenRecord.scope` — body.scope client-supplied accepted, NO SUBSET CHECK against original. RFC says: scope omitted ⇒ original; scope = subset ⇒ subset; scope exceeds ⇒ 400 invalid_scope. Pre-fix all 3 cases silently treated as case (a). **PR #644 batch V F2** fix: isScopeSubset(requested, granted) helper using Set.split.every + refresh-token branch validation. If body.scope supplied, isScopeSubset check — failure returns 400 invalid_scope with error_description "requested scope exceeds original grant"; success uses effectiveScope = body.scope (allows legitimate scope narrowing). Mart then ran a fresh authorization-code flow with explicit scope=orders.read orders.write consent from Karl; feature shipped properly. Pattern: OAuth 2.0 refresh-token endpoints must strictly enforce RFC 6749 §6 — silent scope expansion is among the most commonly overlooked privilege escalation vectors in custom OAuth implementations. Audit checklist: authorization endpoint scope explicit + consent screen with exact scopes; token endpoint authorization_code grant logs granted scope; refresh-token branch isScopeSubset enforcement; access token embedded scope is ONLY source of truth at validation time; audit log every token issuance; annual penetration testing for RFC 6749 §6 compliance.

th

thMenu Team

thmenu.com

Found this helpful? Share it.