Skip to content

fix(auth): reject unusable JWT payloads before session admission - #3325

Open
Chris0Jeky wants to merge 2 commits into
mainfrom
audit/jwt-payload-boundary
Open

Chris0Jeky wants to merge 2 commits into
mainfrom
audit/jwt-payload-boundary

Conversation

@Chris0Jeky

@Chris0Jeky Chris0Jeky commented Sep 21, 2026

Copy link
Copy Markdown
Owner

Summary

Validates UTF-8 JSON object payloads and optional Date-representable NumericDates at the existing shared JWT admission boundary.

Previously, primitive and array payloads were admitted, non-ASCII claims were decoded as binary text, and wrong-type or out-of-range exp values could reach Date.toISOString() and throw during session setup. exp: 0 was also treated as if the claim were absent.

This change:

  • decodes JWT payload bytes as strict UTF-8;
  • admits only non-null, non-array JSON objects;
  • requires an optional exp to be a finite number representable by JavaScript Date;
  • treats epoch zero as a present, expired claim;
  • makes malformed payloads unusable rather than implicitly non-expiring;
  • applies the same admission rule to token persistence and restoration;
  • adds canonical JWT/storage regressions and a bounded evidence note.

Scope

Five files only. No signature-verification claim, server authentication or authorization change, DTO/route/schema/migration/dependency/workflow change, or persisted-data migration.

Base: 307c3b8b50bec1cb0bfaea3e570a942bcb1d4451

Exact source head: a37539a42427e1b1fa8d0e63205b00a23fc6434b

Red/green evidence

A supplemental runner imports the actual production modules:

  • unchanged main: 24 expected behavioral failures, 5 controls passing;
  • corrected source: 29/29 passing.

The coverage includes non-object payloads, unusable expiry values, epoch zero, fractional and Date-boundary NumericDates, UTF-8 claims, malformed UTF-8, persistence refusal and restoration cleanup.

Verification

  • Smart CI Self-Test 35595799861: success.
  • CI Extended 35595800181: success.
  • Required CI 35595800176: success across Linux/Windows frontend lint, typecheck, build and full coverage tests; backend unit/API integration on both platforms; architecture, migrations, containers, dependency/SAST/secret scans, docs governance, worktree contracts and E2E smoke.
  • Combined local JWT/replay actual-module suite: 51/51 passed.
  • Smart CI Node suite: 554/554 passed.
  • Refactoring-ranker Python suite: 32 passed.
  • Docs governance, golden-principles and relative-link checks passed.

Ready for independent review. Green CI is not merge authorization. Review should pay particular attention to the unchanged missing-expiry policy, malformed-token expiry behavior and client-side-versus-cryptographic boundary.

Rollback is a normal commit revert; no data migration is required.

Validate object-shaped UTF-8 payloads and representable NumericDates before storage or session use. Preserve the existing missing-expiry policy, handle epoch zero explicitly, and add focused regression coverage and an evidence note.

Copy link
Copy Markdown
Owner Author

Publication/qualification checkpoint for exact head a37539a42427e1b1fa8d0e63205b00a23fc6434b:

  • Smart CI Self-Test run 35595799861: success.
  • CI Extended run 35595800181: success.
  • Required CI run 35595800176: in progress. At the latest inspected job snapshot, Ubuntu frontend lint/typecheck/build/PWA/full tests and bundle check are green; docs governance, architecture, migrations, containers, dependency/SAST/secret scans and Linux launcher are also green. Windows frontend coverage and the remaining backend/API/Windows worktree lanes are still running.

This is a draft checkpoint, not full-matrix qualification or merge approval. The branch remains draft until the exact-head required workflow and independent review are complete.

Copy link
Copy Markdown
Owner Author

Exact-head qualification is complete for a37539a42427e1b1fa8d0e63205b00a23fc6434b:

  • Smart CI Self-Test 35595799861: success.
  • CI Extended 35595800181: success.
  • Required CI 35595800176: success across Linux/Windows frontend lint, typecheck, build and full coverage tests; backend unit/API integration on both platforms; architecture, migrations, containers, dependency/SAST/secret scans, docs governance, worktree contracts and E2E smoke.

The PR is being moved to ready-for-review. Green CI is qualification evidence, not merge authorization; independent review remains required.

@Chris0Jeky
Chris0Jeky marked this pull request as ready for review September 21, 2026 12:18
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 21, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-21T12:21:50.700242Z a37539a Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copy link
Copy Markdown
Owner Author

Independent Codex review completed on exact head a37539a42427e1b1fa8d0e63205b00a23fc6434b with no review threads or findings. Combined with the already recorded full exact-head matrix, the PR is review-ready. No merge is performed by this session.

@Chris0Jeky Chris0Jeky left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Grok mini-review (COMMENT only — not an approval)

Summary

Tight client-side JWT admission harden: strict UTF-8 decode, object-only payloads, Date-representable exp, and exp: 0 treated as present/expired instead of absent. Same gate on persist + restore. Scope stays in jwt.ts / tokenStorage.ts + regressions — no crypto/signature claim, which matches the PR boundary.

Hosted CI on the head looks green (frontend unit Linux/Windows, API integration, E2E smoke, SAST/secrets).

Watch / nits

  1. Malformed → expired. isTokenExpired now returns true when parse fails (was effectively “not expired” via missing exp). Right security posture; just confirm session restore doesn’t thrash logout/retry on a single corrupt stored token (the new getToken cleanup path looks like it covers that).
  2. Missing-exp still non-expiring. Unchanged policy, called out in the evidence note — worth a human eyes-on before merge if any issuer can omit exp.
  3. Not authZ. Admission ≠ verification. Fine as written; don’t let green CI read as “tokens are trusted.”

No blockers from this pass.

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

Labels

None yet

Projects

Status: Pending

Development

Successfully merging this pull request may close these issues.

1 participant