Skip to content

fix(cacti-plugin-consortium-static): add jti replay protection to verifyOrganization#4373

Open
bhavyamsharmaa wants to merge 1 commit into
hyperledger-cacti:mainfrom
bhavyamsharmaa:fix/consortium-static-jti-replay-validation
Open

fix(cacti-plugin-consortium-static): add jti replay protection to verifyOrganization#4373
bhavyamsharmaa wants to merge 1 commit into
hyperledger-cacti:mainfrom
bhavyamsharmaa:fix/consortium-static-jti-replay-validation

Conversation

@bhavyamsharmaa

Copy link
Copy Markdown

Summary

  • Adds optional seenJtis: Set<string> parameter to verifyOrganization — if provided, a token whose jti has already been seen is rejected, preventing replay attacks
  • StaticConsortiumRepository owns the Set as private state and passes it on every verifyJWT call
  • Removes the buggy manual expiry check (payload.exp in seconds vs Date.now() in milliseconds); jose's jwtVerify already throws JWTExpired for expired tokens, making the manual check both dead code and incorrect
  • Removes console.error in the catch block; all verification failures now return false uniformly
  • Adds unit tests covering: first-use acceptance, replay rejection, wrong issuer, expired token, and backwards-compatible no-seenJtis mode

Closes #4372

PR Checklist

  • Rebased onto upstream/main and squashed into a single commit
  • Signed-off-by present (git commit -s)
  • Follows Conventional Commits
  • Assisted-by: anthropic:claude-sonnet-4-6 included per AI Guidelines §2.2

@RafaelAPB RafaelAPB left a comment

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.

Thank you for your contribution

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR strengthens JWT verification in @hyperledger/cacti-plugin-consortium-static by adding optional JWT ID (jti) replay protection to verifyOrganization(), wiring it into StaticConsortiumRepository, and adding unit tests for the new behavior.

Changes:

  • Extended verifyOrganization() with an optional seenJtis cache to reject replayed tokens based on jti.
  • Updated StaticConsortiumRepository.verifyJWT() to maintain and pass a replay-cache across verifications.
  • Added unit tests covering valid, replayed, wrong issuer, expired, and “no cache provided” cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/cacti-plugin-consortium-static/src/main/typescript/utils.ts Adds optional jti replay tracking in verifyOrganization() and removes the previous manual expiry/error-string behavior.
packages/cacti-plugin-consortium-static/src/main/typescript/repository/static-consortium-repository.ts Introduces repository-owned replay cache and passes it into verifyOrganization() for every verification.
packages/cacti-plugin-consortium-static/src/test/typescript/unit/verify-organization.test.ts Adds unit coverage for first-use acceptance, replay rejection, wrong issuer, expired token, and backwards-compatible mode without replay tracking.

Comment thread packages/cacti-plugin-consortium-static/src/main/typescript/utils.ts Outdated
@bhavyamsharmaa bhavyamsharmaa force-pushed the fix/consortium-static-jti-replay-validation branch from a92e08a to 5e9fdf3 Compare June 10, 2026 13:23
@bhavyamsharmaa

Copy link
Copy Markdown
Author

Hi @VRamakrishna @sandeepnRES @outSH @AndreAugusto11 — just a gentle ping. The Copilot review comments have been addressed (force-pushed Jun 10) and RafaelAPB has approved. Would appreciate a second review when you get a chance. Happy to make any changes if needed!

@AndreAugusto11 AndreAugusto11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGMT! @bhavyamsharmaa thank you very much for the contribution!

@bhavyamsharmaa bhavyamsharmaa force-pushed the fix/consortium-static-jti-replay-validation branch 2 times, most recently from 45a8c38 to 55880a1 Compare June 14, 2026 18:27
@bhavyamsharmaa

Copy link
Copy Markdown
Author

@RafaelAPB — could you approve the workflow runs so CI can proceed?

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.

Please add these files to gitignore; in fact, the cache should not be in version control

- Add optional seenJtis parameter to verifyOrganization to track used JWT IDs
- StaticConsortiumRepository owns the Map and passes it on each verifyJWT call
- Reject tokens missing exp claim; jwtVerify does not require exp to be present
- Namespace jti cache key as iss:jti to prevent cross-org collisions
- Replace unbounded Set with Map<string, number> storing jti -> exp;
  prune expired entries on each verify call
- Remove buggy manual expiry check (payload.exp seconds vs Date.now() ms
  mismatch); jose's jwtVerify already throws JWTExpired for expired tokens
- Remove console.error in catch block; return false for all failures
- Add unit tests: first-use acceptance, replay rejection, wrong issuer,
  expired token, no-exp token, cross-org same-jti, no-seenJtis mode

Closes hyperledger-cacti#4372

Assisted-by: anthropic:claude-sonnet-4-6
Signed-off-by: Bhavyam Sharma <positionbhavyamsharma@gmail.com>
@bhavyamsharmaa bhavyamsharmaa force-pushed the fix/consortium-static-jti-replay-validation branch from 55880a1 to 8a4181c Compare July 1, 2026 18:32
@bhavyamsharmaa

Copy link
Copy Markdown
Author

@RafaelAPB, Done — removed all five @iroha2 cache zips and reverted the .gitignore change. The cache is no longer in version control.

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.

fix(cacti-plugin-consortium-static): verifyOrganization skips JWT ID (jti) replay validation

4 participants