Skip to content

fix(api): identify client_credentials tokens by a signed grant marker + 3.3.8 changelog - #8329

Merged
JohnMcLear merged 2 commits into
developfrom
fix/oidc-grant-classification
Oct 11, 2026
Merged

JohnMcLear merged 2 commits into
developfrom
fix/oidc-grant-classification

Conversation

@JohnMcLear

Copy link
Copy Markdown
Member

Fix for GHSA-38vj-95q4-gwvx (Medium, CWE-863), plus the CHANGELOG entry for 3.3.8.

The HTTP API classified a JWT as client_credentials when sub matched a configured client_id, which skipped the admin === true check. The provider now signs etherpad_grant: 'client_credentials' into client_credentials tokens (extraParams can't override it), and isApiTokenAuthorized() relies on that marker.

Tests: 2 API tests in api/jwtAdminClaim.ts fail on old code and pass with the fix, and there's unit coverage in OidcProviderSecurity.ts. Full backend suite: 1837 passing; the single failure is the known #7885.

Upgrade note: client_credentials tokens issued before the upgrade are refused with 401 until they're re-issued (they're short-lived).

Reported by Yves Soete of Blacksight LLC (@yssoe).

🤖 Generated with Claude Code

https://claude.ai/code/session_012cFUmwE79DiLX4VsJqoTZV

JohnMcLear and others added 2 commits October 11, 2026 15:35
The HTTP API treated any JWT whose sub matched a configured client_id as a
client_credentials token and skipped the admin === true check, so a user
whose username collided with a client ID got admin API access with a
non-admin authorization_code token. The provider now signs an
etherpad_grant marker into client_credentials tokens (not overridable by
extraParams) and the API relies on it.

Reported by Yves Soete of Blacksight LLC (BS-2026-063).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WnNeNQpAJ5TWNZka4yugCw
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012cFUmwE79DiLX4VsJqoTZV
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix HTTP API privilege escalation from colliding OIDC identities

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Identify client-credentials tokens by a signed grant marker, preventing non-admin users with
 colliding names from bypassing authorization.
• Add authorization regression tests and document the 3.3.8 security fix and token re-issuance
 requirement.
Diagram

graph TD
  Provider["OIDC Provider"] --> Token["Signed JWT"] --> Verify["API Verification"] --> Grant{"Grant marker?"}
  Grant -->|client credentials| Client["Configured client?"] -->|yes| Access["HTTP API access"]
  Grant -->|otherwise| Admin["Admin strictly true?"] -->|yes| Access
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Introspect tokens with the OIDC provider
  • ➕ Could classify grants using provider-side token information rather than a new JWT claim.
  • ➖ Adds a lookup to API authorization and depends on provider introspection being available for these tokens.

Recommendation: Keep the signed-marker approach: it fixes the subject-collision vulnerability while preserving local JWT verification. The marker is protected from extraParams overrides, and marked tokens still require a configured client ID. Reviewers should account for the documented 401 response for pre-upgrade client-credentials tokens until re-issuance.

Files changed (6) +199 / -25

Bug fix (3) +65 / -25
APIHandler.tsAuthorize verified JWTs without inferring their grant from subject +7/-11

Authorize verified JWTs without inferring their grant from subject

• Replaces subject-to-client-ID classification with the shared authorization check. A colliding non-admin user subject can no longer skip the strict admin-claim requirement.

src/node/handler/APIHandler.ts

OAuth2Provider.tsStamp client-credentials tokens with protected grant claims +4/-14

Stamp client-credentials tokens with protected grant claims

• Uses the shared claim builder when issuing client-credentials tokens, preserving configured extra claims while adding the grant marker.

src/node/security/OAuth2Provider.ts

OidcProviderSecurity.tsCentralize grant marking and API token authorization +54/-0

Centralize grant marking and API token authorization

• Adds a client-credentials claim builder that prevents extraParams from overriding the marker. Adds an authorization predicate that accepts marked tokens only for configured clients and otherwise requires admin to be strictly true.

src/node/security/OidcProviderSecurity.ts

Tests (2) +121 / -0
OidcProviderSecurity.tsCover grant claims and authorization decisions +57/-0

Cover grant claims and authorization decisions

• Tests colliding subjects, valid and unknown clients, admin users, unexpected markers, and missing payloads. Also verifies extra-claim preservation and resistance to marker overrides.

src/tests/backend/specs/OidcProviderSecurity.ts

jwtAdminClaim.tsExercise JWT grant classification through the HTTP API +64/-0

Exercise JWT grant classification through the HTTP API

• Adds signed-token API tests rejecting colliding non-admin user tokens and marked tokens for unknown clients. Confirms a marked token for a configured client remains authorized.

src/tests/backend/specs/api/jwtAdminClaim.ts

Documentation (1) +13 / -0
CHANGELOG.mdDocument the 3.3.8 security release +13/-0

Document the 3.3.8 security release

• Describes the HTTP API privilege escalation, the signed-marker fix, reporter credit, and the need to re-issue older client-credentials tokens. Also records the numeric or boolean admin-password and reduced-motion dropdown fixes.

CHANGELOG.md

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can tweak Display settings with a live preview to see your comment before it ships

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@JohnMcLear
JohnMcLear merged commit d50b888 into develop Oct 11, 2026
34 checks passed
@JohnMcLear
JohnMcLear deleted the fix/oidc-grant-classification branch October 11, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant