Skip to content

JwtToken accepts segments that are not base64url: embedded spaces ("eyJh bGci OiJI UzI1 NiJ9.…"), = padding and +// all validate #329

Description

@matt-edmondson

What's wrong

JwtToken's XML doc says it is "three '.'-separated base64url segments" (Semantics.Strings.Identifiers/JwtToken.cs:8), and the attribute says the header and payload "base64url-decode". IsJwtTokenAttribute.DecodesToJsonObject (Semantics.Strings.Identifiers/IsJwtTokenAttribute.cs:52-72) actually does the following:

  1. It maps -→+ and _→/, but does not reject +, / or = already in the segment, all of which are outside the base64url alphabet (RFC 7515 §2 also forbids padding).
  2. It pads based on segment.Length % 4 and then calls Convert.FromBase64String, which silently skips whitespace. The length check counts the whitespace, so a segment with embedded spaces decodes whenever the spaces happen to make the length work.

JwtToken does no canonicalization, so the malformed text is stored verbatim, and every downstream JWT library will reject it.

Reproduction (built from HEAD):

JwtToken.Create("eyJh bGci OiJI UzI1 NiJ9.eyJzdWIiOiIxIn0.sig")  -> ACCEPTED (spaces inside the header)
JwtToken.Create("e30=.e30=.x")                                   -> ACCEPTED (standard-base64 padding)
JwtToken.Create("eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIn0.sig")      -> accepted (correct)

This is the same root cause as #316 ([IsBase64] and whitespace), but in a separate validator in the Identifiers package, so fixing #316 does not fix it.

Suggested fix / acceptance criteria

  • Before decoding, require each of the header and payload segments to match ^[A-Za-z0-9_-]+$ (no =, +, /, or whitespace), and reject a segment whose length is 1 mod 4. The signature segment should match ^[A-Za-z0-9_-]*$ (it may be empty, as documented).
  • Tests: both accepted strings above are rejected, and the existing valid and alg=none vectors still pass.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions