Skip to content

fix(isJWT): validate header and payload decode to valid JSON objects#2689

Open
abhu85 wants to merge 2 commits intovalidatorjs:masterfrom
abhu85:fix/2511-isJWT-validate-json
Open

fix(isJWT): validate header and payload decode to valid JSON objects#2689
abhu85 wants to merge 2 commits intovalidatorjs:masterfrom
abhu85:fix/2511-isJWT-validate-json

Conversation

@abhu85
Copy link

@abhu85 abhu85 commented Mar 16, 2026

Summary

  • Fixes isJWT to properly validate that JWT header and payload decode to valid JSON objects
  • Adds test cases for previously incorrect validations (e.g., foo.bar.baz, .babelrc.cjs)
  • No breaking changes - only rejects strings that were incorrectly accepted before

Problem

The current isJWT validator only checks if the three dot-separated parts are valid Base64, but doesn't verify that the decoded header and payload are valid JSON objects as required by RFC 7519.

This causes false positives:

isJWT('foo.bar.')  // true (incorrect - "foo" is not valid JSON)
isJWT('.babelrc.cjs')  // true (incorrect)
isJWT('..')  // true (incorrect)

Solution

Per RFC 7519, a JWT consists of:

  1. Header - MUST be a JSON object (contains alg, typ, etc.)
  2. Payload - MUST be a JSON object (the claims)
  3. Signature - Binary data (not required to be JSON)

The fix adds JSON parsing validation for the header and payload parts after Base64 decoding, ensuring they are valid JSON objects (not arrays, strings, or other types).

Test Plan

  • All existing tests pass (317 passing)
  • Added test cases for issue examples (foo.bar.baz, .babelrc.cjs, .., .t.)
  • Linting passes
  • Coverage maintained at 99%+

Compatibility

  • No breaking changes for valid JWTs
  • Backwards compatible - only rejects previously invalid inputs
  • Works in both Node.js and browser environments

Fixes #2511

…ects (validatorjs#2511)

The isJWT validator now properly validates that the header (first part) and
payload (second part) of a JWT decode to valid JSON objects, not just valid
Base64 strings.

Per RFC 7519, a JWT consists of three Base64URL-encoded parts:
- Header: MUST be a JSON object containing at least "alg"
- Payload: MUST be a JSON object (the claims)
- Signature: Binary data (not required to be JSON)

Previously, strings like "foo.bar.baz" or ".babelrc.cjs" would incorrectly
return true because they matched the Base64 pattern, even though decoding
them does not produce valid JSON.

Fixes validatorjs#2511

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@codecov
Copy link

codecov bot commented Mar 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (88e0d3d) to head (1602dfb).
⚠️ Report is 6 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff            @@
##            master     #2689   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          114       114           
  Lines         2590      2612   +22     
  Branches       659       664    +5     
=========================================
+ Hits          2590      2612   +22     

☔ 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.

Adds tests for 100% coverage of the new isValidJSONObject function:
- Edge cases for JSON types that aren't objects (arrays, null, primitives)
- Buffer.from() fallback path (when atob is unavailable)
- Fallback return false path (when neither atob nor Buffer available)

Fixes validatorjs#2511 coverage requirements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.

isJWT does not check whether the decoded sections are valid JSON

1 participant