feat: add jwt validation action and docs#1348
feat: add jwt validation action and docs#1348fabian-hiller merged 16 commits intoopen-circle:mainfrom
Conversation
|
@yslpn is attempting to deploy a commit to the Valibot Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull Request Overview
This PR adds JWT (JSON Web Token) validation functionality to the library. It introduces a new validation action that verifies whether a string conforms to the three-part Base64URL-encoded structure of a JWT token.
- Adds
jwt()validation action with regex-based format checking - Implements
JwtActionandJwtIssuetypes with appropriate generics - Includes comprehensive test coverage for valid/invalid JWT formats
Reviewed Changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| website/src/routes/api/menu.md | Adds menu entries for jwt, JwtAction, and JwtIssue API documentation |
| website/src/routes/api/(types)/JwtIssue/properties.ts | Defines property metadata for JwtIssue type documentation |
| website/src/routes/api/(types)/JwtIssue/index.mdx | Documents the JwtIssue interface |
| website/src/routes/api/(types)/JwtAction/properties.ts | Defines property metadata for JwtAction type documentation |
| website/src/routes/api/(types)/JwtAction/index.mdx | Documents the JwtAction interface |
| website/src/routes/api/(actions)/jwt/properties.ts | Defines property metadata for jwt function documentation |
| website/src/routes/api/(actions)/jwt/index.mdx | Provides comprehensive documentation and examples for the jwt validation action |
| library/src/regex.ts | Adds JWT_REGEX pattern for validating JWT token structure |
| library/src/actions/jwt/jwt.ts | Implements the jwt validation action with JwtAction and JwtIssue interfaces |
| library/src/actions/jwt/jwt.test.ts | Adds runtime tests for jwt validation with valid/invalid test cases |
| library/src/actions/jwt/jwt.test-d.ts | Adds type-level tests for jwt validation action |
| library/src/actions/jwt/index.ts | Exports jwt validation action |
| library/src/actions/index.ts | Re-exports jwt from actions index |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Sorry for my late replay! Thank you for this PR! We really need this action! I will review this PR when working on Valibot v1.3. |
|
Are you already a member of the Valibot Discord? |
Yes. Same username as on GitHub.
Agreed. I'll be here if any fixes are needed. Or if there are any questions. |
|
@coderabbitai please review this PR |
|
✅ Actions performedFull review triggered. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new JWS compact validation action: types, runtime validator using a new regex, tests (runtime and type-level), JSON Schema conversion support, and full API/type documentation and navigation/menu entries. Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@library/src/regex.ts`:
- Line 120: The current JWT_REGEX allows '=' padding and disallows unsecured
JWTs with an empty signature; update the JWT_REGEX constant so it matches the
standard compact JWT form: exactly three dot-separated Base64URL segments where
the first two segments require one or more Base64URL chars ([A-Za-z0-9_-]+) and
the third (signature) may be empty ([A-Za-z0-9_-]*), and do not permit '='
padding; replace the existing /^[-\w]+={0,2}\.[-\w]+={0,2}\.[-\w]+={0,2}$/u with
a regex that enforces those token characters for JWT_REGEX so jwt() (used at
jwt.ts:92-97) correctly classifies tokens.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: dceccdc4-321e-4bf2-9875-163b16fb87ef
📒 Files selected for processing (13)
library/src/actions/index.tslibrary/src/actions/jwt/index.tslibrary/src/actions/jwt/jwt.test-d.tslibrary/src/actions/jwt/jwt.test.tslibrary/src/actions/jwt/jwt.tslibrary/src/regex.tswebsite/src/routes/api/(actions)/jwt/index.mdxwebsite/src/routes/api/(actions)/jwt/properties.tswebsite/src/routes/api/(types)/JwtAction/index.mdxwebsite/src/routes/api/(types)/JwtAction/properties.tswebsite/src/routes/api/(types)/JwtIssue/index.mdxwebsite/src/routes/api/(types)/JwtIssue/properties.tswebsite/src/routes/api/menu.md
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
library/src/actions/jwt/jwt.test.ts (1)
125-130: Use a real Unicode character in the last invalid-character case.Line 129 currently contains the literal text
\u00a9because the backslash is escaped, so this only proves backslashes are rejected. If the goal is non-ASCII coverage, use©or\u00a9directly in the string literal.🧪 Tiny fixture fix
- 'header.payload.sig\\u00a9nature', + 'header.payload.sig\u00a9nature',🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@library/src/actions/jwt/jwt.test.ts` around lines 125 - 130, The test 'for invalid characters' is using an escaped backslash sequence "\\u00a9" instead of an actual Unicode character; update the third test string passed to expectActionIssue (inside the test named 'for invalid characters') to include a real non-ASCII character (e.g., "©" or the literal "\u00a9" without an extra backslash) so the case exercises Unicode rejection rather than just backslash escaping; keep the other two inputs and variables (action, baseIssue) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@library/src/actions/jwt/jwt.test.ts`:
- Around line 67-76: The test 'for valid JWTs' currently includes real-looking
JWT strings that trigger secret scanners; change the fixtures used in
expectNoActionIssue to synthetic base64url-safe segments instead (e.g., generate
header, payload, signature strings that match JWT_REGEX but are not real
secrets) so coverage of jwt() / JWT_REGEX remains the same; update the array
passed to expectNoActionIssue in the test (and any other similar arrays in this
file) to use these synthetic base64url-safe segment placeholders rather than raw
JWT literals.
---
Nitpick comments:
In `@library/src/actions/jwt/jwt.test.ts`:
- Around line 125-130: The test 'for invalid characters' is using an escaped
backslash sequence "\\u00a9" instead of an actual Unicode character; update the
third test string passed to expectActionIssue (inside the test named 'for
invalid characters') to include a real non-ASCII character (e.g., "©" or the
literal "\u00a9" without an extra backslash) so the case exercises Unicode
rejection rather than just backslash escaping; keep the other two inputs and
variables (action, baseIssue) unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 57a06127-a2bc-41a9-9a7a-d1fb4f23f7e1
📒 Files selected for processing (3)
library/src/actions/jwt/jwt.test.tslibrary/src/regex.tswebsite/src/routes/api/(actions)/jwt/index.mdx
🚧 Files skipped from review as they are similar to previous changes (2)
- website/src/routes/api/(actions)/jwt/index.mdx
- library/src/regex.ts
|
Thank you for this PR. I am trying to get most important PRs merged in the next weeks. One thing I’m not sure about is whether regex is the right boundary for The current implementation seems reasonable if the intention is just a lightweight structural check for the common 3-part JWT/JWS shape. In that sense, regex is simple, fast, and consistent with several other format validators in the library. That said, it might be worth aligning on what jwt() is expected to mean:
For example, this currently only allows the 3-part compact form, so it would exclude JWTs represented as JWE compact serialization with 5 parts. On the other hand, it will also accept strings that are just three base64url-like segments even if the decoded header/payload are not valid JSON. I don’t see this as a blocker by itself, but I think it would be good to decide explicitly which contract we want the jwt() action to have, and then shape the implementation/docs around that. |
commit: |
Thanks, this makes sense to me, and I agree the main question is the contract rather than regex itself. To make that boundary explicit, I renamed the action from This also leaves room to add I also updated the documentation to describe the current boundaries explicitly: Given that, I think the lightweight |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
library/src/actions/jwsCompact/jwsCompact.test.ts (1)
73-79: Use synthetic fixtures here instead of literal JWT samples.Several of these fixtures are already matching secret-scanning as uncovered JWTs. Since
jwsCompact()only validates structure, base64url-looking gibberish exercises the same paths without creating high-signal security noise in the test suite.Also applies to: 117-117
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@library/src/actions/jwsCompact/jwsCompact.test.ts` around lines 73 - 79, Replace the hard-coded JWT strings in the jwsCompact.test.ts fixtures with synthetic, non-sensitive base64url-like strings (e.g., construct header.payload.signature patterns programmatically) so the jwsCompact() tests still exercise structure parsing without containing real or high-signal JWT samples; locate the array of fixtures used by the jwsCompact tests (the entries currently containing 'eyJ...' strings including the one ending with a trailing dot) and substitute them with generated placeholders that mirror "header.payload.signature" shape (keeping variations such as empty signature or different alg fields) to preserve coverage while avoiding secret-scanning hits.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@library/src/actions/jwsCompact/jwsCompact.ts`:
- Around line 99-103: The JWS_COMPACT_REGEX used by jwsCompact (referenced via
the requirement property in the '~run' method) currently rejects compact
serializations with an empty payload; update the regex definition named
JWS_COMPACT_REGEX in library/src/regex.ts to allow an empty middle (payload)
segment (change the base64url quantifier from one-or-more to zero-or-more) so
the dataset.check in '~run' accepts empty payloads, and add a regression test
exercising jwsCompact() with a valid compact serialization whose payload encodes
to the empty string to prevent regressions; ensure the behavior in '~run' and
_addIssue remains unchanged aside from accepting the empty payload case.
In `@website/src/routes/api/`(actions)/jwsCompact/index.mdx:
- Around line 3-37: Reword the doc for the jwsCompact action to keep the public
contract purely structural: replace references to "JWT strings" and implications
of signature/semantics with language that describes only the three-part JWS
compact shape (un-padded Base64URL segments) and that an empty/absent third
segment is valid syntax; update the description, summary lines that read like
JWT semantics (mentions of "signed" or 'alg: "none"') to clarify you are not
decoding or verifying headers/ signatures and that acceptance of an empty third
segment is purely a structural allowance, not an inference about decoded header
or algorithm.
In `@website/src/routes/api/`(types)/JwsCompactAction/index.mdx:
- Around line 3-15: Update the documentation text in the JwsCompactAction MDX to
remove the broader "JWT" wording and explicitly describe structural JWS compact
validation: change lines referencing "JWT validation" and "JWT strings" to
phrases like "JWS compact validation" and "JWS compact serialized strings" so
the description matches the narrower jwsCompact contract; apply the same exact
wording changes in the JwsCompactIssue MDX so both docs consistently reference
JWS compact validation and the jwsCompact function by name.
---
Nitpick comments:
In `@library/src/actions/jwsCompact/jwsCompact.test.ts`:
- Around line 73-79: Replace the hard-coded JWT strings in the
jwsCompact.test.ts fixtures with synthetic, non-sensitive base64url-like strings
(e.g., construct header.payload.signature patterns programmatically) so the
jwsCompact() tests still exercise structure parsing without containing real or
high-signal JWT samples; locate the array of fixtures used by the jwsCompact
tests (the entries currently containing 'eyJ...' strings including the one
ending with a trailing dot) and substitute them with generated placeholders that
mirror "header.payload.signature" shape (keeping variations such as empty
signature or different alg fields) to preserve coverage while avoiding
secret-scanning hits.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d1a09372-5ad9-4a25-812f-bae4bda1b74b
📒 Files selected for processing (15)
library/src/actions/index.tslibrary/src/actions/jwsCompact/index.tslibrary/src/actions/jwsCompact/jwsCompact.test-d.tslibrary/src/actions/jwsCompact/jwsCompact.test.tslibrary/src/actions/jwsCompact/jwsCompact.tslibrary/src/regex.tspackages/to-json-schema/src/converters/convertAction/convertAction.test.tspackages/to-json-schema/src/converters/convertAction/convertAction.tswebsite/src/routes/api/(actions)/jwsCompact/index.mdxwebsite/src/routes/api/(actions)/jwsCompact/properties.tswebsite/src/routes/api/(types)/JwsCompactAction/index.mdxwebsite/src/routes/api/(types)/JwsCompactAction/properties.tswebsite/src/routes/api/(types)/JwsCompactIssue/index.mdxwebsite/src/routes/api/(types)/JwsCompactIssue/properties.tswebsite/src/routes/api/menu.md
🚧 Files skipped from review as they are similar to previous changes (1)
- library/src/regex.ts
… structural validation clarity
|
I will probably merged this now but wanted to ask if the regex can be shorten without changing it meaning or perf. Feel free to check and create a PR if so. const JWS_COMPACT_REGEX = /^(?:[\w-]{4})*(?:[\w-]{2,4})\.(?:[\w-]{4})*(?:[\w-]{2,4})?\.(?:[\w-]{4})*(?:[\w-]{2,4})?$/u |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
|
Valibot v1.3 is available. Feel free to submit and expense of $50 for all your contributions for Valibot v1.3 via Open Collective. |
Overview
jwt()action tojwsCompact()and scope it to the 3-part JWS compact serializationjweCompact()action for 5-part compact tokens and keepjwt()reserved for broader JWT support@valibot/to-json-schemasupport forjwsCompact()Summary by CodeRabbit
New Features
Tests
Documentation
Chores