Skip to content

Comments

fix: JWT Algorithm Confusion in Google Auth Adapter (GHSA-4q3h-vp4r-prv2)#10073

Merged
mtrezza merged 3 commits intoparse-community:release-8.x.xfrom
mtrezza:fix/ghsa-4q3h-8.x
Feb 23, 2026
Merged

fix: JWT Algorithm Confusion in Google Auth Adapter (GHSA-4q3h-vp4r-prv2)#10073
mtrezza merged 3 commits intoparse-community:release-8.x.xfrom
mtrezza:fix/ghsa-4q3h-8.x

Conversation

@mtrezza
Copy link
Member

@mtrezza mtrezza commented Feb 23, 2026

Pull Request

Issue

JWT Algorithm Confusion in Google Auth Adapter (GHSA-4q3h-vp4r-prv2).

Tasks

  • Add tests
  • Add changes to documentation (guides, repository pages, code comments)
  • Add security check
  • Add new Parse Error codes to Parse JS SDK

Summary by CodeRabbit

  • Bug Fixes
    • Enhanced security by enforcing RS256 algorithm during authentication token verification across Google, Apple, and Facebook adapters, preventing algorithm confusion attacks.
    • Improved error handling for missing or invalid signing keys with clearer error messages.
    • Added caching optimization for Google authentication signing key retrieval to improve performance.

@parse-github-assistant
Copy link

I will reformat the title to use the proper commit message syntax.

@parse-github-assistant parse-github-assistant bot changed the title fix: ghsa 4q3h 8.x fix: Ghsa 4q3h 8.x Feb 23, 2026
@parse-github-assistant
Copy link

parse-github-assistant bot commented Feb 23, 2026

🚀 Thanks for opening this pull request!

@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

📝 Walkthrough

Walkthrough

The changes implement a security fix for JWT algorithm confusion vulnerabilities across authentication adapters. The update hardcodes the RS256 algorithm during JWT verification instead of trusting the token header, replaces manual JWKS handling with the dedicated jwks-rsa library in the Google adapter, and enhances error handling for invalid signing keys. Tests are updated to verify the new verification flow and security enforcement.

Changes

Cohort / File(s) Summary
Google Auth Adapter Refactoring
src/Adapters/Auth/google.js
Replaced manual JWKS fetching with jwks-rsa client library. Introduced getGoogleKeyByKeyId function with configurable caching (cacheMaxEntries, cacheMaxAge). Hardcoded RS256 algorithm for jwt.verify. Enhanced error handling for missing signing keys with OBJECT_NOT_FOUND status. Removed legacy RSA/PEM conversion utilities.
Apple & Facebook Auth Adapters
src/Adapters/Auth/apple.js, src/Adapters/Auth/facebook.js
Removed dynamic algorithm extraction from token headers. Hardcoded jwt.verify to use ['RS256'] algorithm instead of token-provided algorithm values.
Authentication Test Suite
spec/AuthenticationAdapters.spec.js
Added security tests (GHSA-4q3h-vp4r-prv2) verifying RS256 algorithm enforcement and rejection of forged tokens across Google, Apple, and Facebook adapters. Restructured test token objects from nested (header: { kid, alg }) to flat (kid, alg) format. Mocked getHeaderFromToken, getSigningKey, and jwt.verify to ensure consistent algorithm usage.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Adapter as Auth Adapter
    participant JWKSClient as JWKS Client
    participant JWTLib as JWT Library
    
    Client->>Adapter: verifyIdToken(token, options)
    Adapter->>Adapter: getHeaderFromToken(token)
    Adapter->>Adapter: Extract keyId from header
    Adapter->>JWKSClient: getSigningKey(keyId)
    JWKSClient->>JWKSClient: Check cache
    alt Key in cache
        JWKSClient-->>JWKSClient: Return cached key
    else Key not in cache
        JWKSClient->>JWKSClient: Fetch from JWKS endpoint
        JWKSClient->>JWKSClient: Cache result
    end
    JWKSClient-->>Adapter: Return publicKey
    Adapter->>JWTLib: jwt.verify(token, publicKey, {algorithms: ['RS256']})
    JWTLib->>JWTLib: Verify signature with RS256 only
    alt Valid signature
        JWTLib-->>Adapter: Decoded payload
        Adapter-->>Client: Verified token data
    else Invalid signature or wrong algorithm
        JWTLib-->>Adapter: Verification error
        Adapter-->>Client: Error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description identifies the security issue (GHSA-4q3h-vp4r-prv2) and checks off completed tasks, but lacks detailed explanation of the approach and implementation. Provide a clear 'Approach' section describing how the JWT algorithm confusion vulnerability was fixed, such as details on hardcoding RS256 and implementing jwks-rsa.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the core security fix: hardcoding RS256 algorithm in JWT verification to mitigate algorithm confusion attacks (GHSA-4q3h-vp4r-prv2), which aligns with the changeset's main modifications across Google, Apple, and Facebook auth adapters.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@parseplatformorg
Copy link
Contributor

parseplatformorg commented Feb 23, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@mtrezza
Copy link
Member Author

mtrezza commented Feb 23, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
spec/AuthenticationAdapters.spec.js (1)

972-976: Pre-existing mock inconsistency: getHeaderFromToken returns nested object, causing keyId to be undefined.

In this test (and several other unchanged Apple/Facebook tests), getHeaderFromToken is mocked to return the full fakeDecodedToken object (with a nested .header property) rather than fakeDecodedToken.header. Since the adapter destructures { kid: keyId } from the return value, keyId becomes undefined. The test still passes because getSigningKey is broadly mocked and jwt.verify fails early on the malformed token—but the mock doesn't accurately reflect the real call.

This is pre-existing and not introduced by this PR, but while you're touching adjacent lines it would be a good cleanup to align these mocks with the flat-object pattern used in the newly added tests (e.g., lines 959, 529, 1318).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@spec/AuthenticationAdapters.spec.js` around lines 972 - 976, The mocks for
getHeaderFromToken return a nested object which makes the adapter's
destructuring ({ kid: keyId }) yield undefined; update the tests (including this
one and other Apple/Facebook tests) to have spyOn(authUtils,
'getHeaderFromToken') return the flat header object (i.e.,
fakeDecodedToken.header) instead of the whole fakeDecodedToken so keyId is set
correctly, and ensure getSigningKey remains mocked via authUtils.getSigningKey
to resolve to fakeSigningKey to match the real call shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@spec/AuthenticationAdapters.spec.js`:
- Around line 972-976: The mocks for getHeaderFromToken return a nested object
which makes the adapter's destructuring ({ kid: keyId }) yield undefined; update
the tests (including this one and other Apple/Facebook tests) to have
spyOn(authUtils, 'getHeaderFromToken') return the flat header object (i.e.,
fakeDecodedToken.header) instead of the whole fakeDecodedToken so keyId is set
correctly, and ensure getSigningKey remains mocked via authUtils.getSigningKey
to resolve to fakeSigningKey to match the real call shape.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 035b9b5 and 81814f1.

📒 Files selected for processing (4)
  • spec/AuthenticationAdapters.spec.js
  • src/Adapters/Auth/apple.js
  • src/Adapters/Auth/facebook.js
  • src/Adapters/Auth/google.js

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 23, 2026
@mtrezza mtrezza changed the title fix: Ghsa 4q3h 8.x fix: JWT Algorithm Confusion in Google Auth Adapter (GHSA-4q3h-vp4r-prv2) Feb 23, 2026
@mtrezza mtrezza merged commit 9b94083 into parse-community:release-8.x.x Feb 23, 2026
24 of 26 checks passed
parseplatformorg pushed a commit that referenced this pull request Feb 23, 2026
## [8.6.3](8.6.2...8.6.3) (2026-02-23)

### Bug Fixes

* JWT Algorithm Confusion in Google Auth Adapter ([GHSA-4q3h-vp4r-prv2](https://github.com/parse-community/parse-server/security/advisories/GHSA-4q3h-vp4r-prv2)) ([#10073](#10073)) ([9b94083](9b94083))
@parseplatformorg
Copy link
Contributor

🎉 This change has been released in version 8.6.3

@parseplatformorg parseplatformorg added the state:released-8.x.x Released as LTS version label Feb 23, 2026
@mtrezza mtrezza deleted the fix/ghsa-4q3h-8.x branch February 23, 2026 22:11
@codecov
Copy link

codecov bot commented Feb 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.60%. Comparing base (155c6ad) to head (3b7625d).
⚠️ Report is 3 commits behind head on release-8.x.x.

Additional details and impacted files
@@                Coverage Diff                @@
##           release-8.x.x   #10073      +/-   ##
=================================================
+ Coverage          92.58%   92.60%   +0.02%     
=================================================
  Files                191      191              
  Lines              15543    15509      -34     
  Branches             177      177              
=================================================
- Hits               14390    14362      -28     
+ Misses              1141     1135       -6     
  Partials              12       12              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

state:released-8.x.x Released as LTS version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants