Skip to content

fix(mcp): fail closed when the JWT verifier has no pinned algorithm#41296

Open
rusackas wants to merge 1 commit into
masterfrom
fix/mcp-jwt-pin-algorithm
Open

fix(mcp): fail closed when the JWT verifier has no pinned algorithm#41296
rusackas wants to merge 1 commit into
masterfrom
fix/mcp-jwt-pin-algorithm

Conversation

@rusackas

Copy link
Copy Markdown
Member

SUMMARY

DetailedJWTVerifier.load_access_token rejected the none algorithm and otherwise compared the token's alg against self.algorithm — but only inside an if self.algorithm guard. The pinned value is currently always populated because the upstream JWTVerifier defaults algorithm to RS256, so the verifier was effectively relying on that upstream default to keep the algorithm pinned.

This makes the pinning explicit and self-contained: if no algorithm is pinned, the verifier now rejects the token (fail closed) rather than validating against whatever algorithm family the key/library would otherwise permit. It removes the implicit dependency on the upstream default.

This is a small defense-in-depth change — under current behavior self.algorithm is always set — so there is no functional change for normally constructed verifiers.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — backend verification behavior.

TESTING INSTRUCTIONS

Unit test added in tests/unit_tests/mcp_service/test_jwt_verifier.py (test_unpinned_algorithm_is_rejected): an unpinned verifier rejects a signed token with reason "No signing algorithm pinned".

Run: pytest tests/unit_tests/mcp_service/test_jwt_verifier.py

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

DetailedJWTVerifier.load_access_token only rejected the "none" algorithm and
otherwise compared the token algorithm against self.algorithm — but only when
self.algorithm was truthy. The pinned value is currently always present because
the upstream JWTVerifier defaults it to RS256, so the verifier relied on that
upstream default for a security property.

Make the pinning explicit: reject tokens when no algorithm is pinned rather
than validating against an unconstrained algorithm family. This removes the
implicit dependency on the upstream default and fails closed if the pinned
algorithm is ever absent.

Adds a unit test asserting an unpinned verifier rejects signed tokens.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rusackas rusackas added the asvs label Jun 23, 2026
@dosubot dosubot Bot added the authentication Related to authentication label Jun 23, 2026
@bito-code-review

bito-code-review Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #7088bd

Actionable Suggestions - 0
Additional Suggestions - 1
  • tests/unit_tests/mcp_service/test_jwt_verifier.py - 1
    • Missing non-leak assertion · Line 105-106
      The assertion only checks for exact string equality but doesn't verify algorithm names are excluded from the reason, unlike the analogous test_algorithm_mismatch which asserts both 'RS256' and 'HS256' are absent from the reason.
Review Details
  • Files reviewed - 2 · Commit Range: 6dacfc1..6dacfc1
    • superset/mcp_service/jwt_verifier.py
    • tests/unit_tests/mcp_service/test_jwt_verifier.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo



@pytest.mark.asyncio
async def test_unpinned_algorithm_is_rejected(hs256_verifier):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add full type annotations to the new async test function, including the hs256_verifier parameter type and an explicit -> None return type. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This is a newly added Python async test function, and it omits both a parameter type hint for
hs256_verifier and an explicit -> None return annotation. That matches the custom rule
requiring new Python functions to be fully typed.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/mcp_service/test_jwt_verifier.py
**Line:** 87:87
**Comment:**
	*Custom Rule: Add full type annotations to the new async test function, including the `hs256_verifier` parameter type and an explicit `-> None` return type.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@bito-code-review

Copy link
Copy Markdown
Contributor

The suggestion to add type annotations to the new async test function is correct and aligns with best practices for maintaining a typed codebase. You can resolve this by updating the function signature in tests/unit_tests/mcp_service/test_jwt_verifier.py as follows:

@pytest.mark.asyncio
async def test_unpinned_algorithm_is_rejected(hs256_verifier: Any) -> None:

(Note: Ensure Any is imported from typing if not already available in the file.)

There are no other comments on this PR to address. Would you like me to proceed with any other changes?

tests/unit_tests/mcp_service/test_jwt_verifier.py

@pytest.mark.asyncio
async def test_unpinned_algorithm_is_rejected(hs256_verifier: Any) -> None:

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.34%. Comparing base (3b46a5f) to head (6dacfc1).

Files with missing lines Patch % Lines
superset/mcp_service/jwt_verifier.py 0.00% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #41296      +/-   ##
==========================================
- Coverage   64.34%   64.34%   -0.01%     
==========================================
  Files        2653     2653              
  Lines      144952   144957       +5     
  Branches    33433    33434       +1     
==========================================
- Hits        93272    93267       -5     
- Misses      49996    50004       +8     
- Partials     1684     1686       +2     
Flag Coverage Δ
hive 39.27% <0.00%> (-0.01%) ⬇️
mysql 57.99% <0.00%> (-0.01%) ⬇️
postgres 58.06% <0.00%> (-0.01%) ⬇️
presto 40.85% <0.00%> (-0.01%) ⬇️
python 59.50% <0.00%> (-0.01%) ⬇️
sqlite 57.71% <0.00%> (-0.01%) ⬇️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 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

asvs authentication Related to authentication size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants