Skip to content

Conversation

@Nesopie
Copy link
Collaborator

@Nesopie Nesopie commented Nov 28, 2025

Note

Packs eat_nonce[0] and image hash outputs, tightens nonce length handling, improves JSON array/value parsing, adds eat_nonce[1] support in prepare, and introduces a GCP JWT test script.

  • GCP JWT Circuit (gcp_jwt_verifier.circom):
    • Output changes: replace raw arrays with packed outputs using PackBytes for eat_nonce[0] and image_hash.
    • Length/limits: set MAX_EAT_NONCE_B64_LENGTH to 74 and use it in max-length check; compute packed chunk sizes.
    • Minor: include @openpassport/zk-email-circuits/utils/bytes.circom.
  • JSON Extraction (verifyJSONFieldExtraction.circom):
    • Parsing: allow value to start immediately after : with a quote or with :["; validate value_offset via first value char.
    • Trailing char: accept either ] or , after the closing quote.
  • Prepare Script (prepare.ts):
    • Add handling and offsets for eat_nonce[1]; emit eat_nonce_1_b64_length.
    • Remove unused decoded nonce logging.
  • Tooling:
    • Add test-gcp-jwt-verifier script in package.json.

Written by Cursor Bugbot for commit 32a9dc7. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • Added test suite for GCP JWT verifier.
  • Updates

    • Modified JWT verification output formats to use packed byte representation.
    • Enhanced JSON field extraction validation logic with improved parsing flow.
    • Updated nonce field processing in JWT payload verification.

✏️ Tip: You can customize this high-level summary in your review settings.

@Nesopie Nesopie merged commit d5d0879 into dev Nov 28, 2025
6 of 14 checks passed
@Nesopie Nesopie deleted the fix/jwt-output branch November 28, 2025 19:44
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 28, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This PR refactors the GCP JWT verifier circuit to use packed byte representations for outputs, extends the preprocessing logic to handle a second eat_nonce field extracted from the payload, and refines JSON field extraction parsing to correctly handle quoted values terminated by either closing brackets or commas.

Changes

Cohort / File(s) Summary
Circuit output packing
circuits/circuits/gcp_jwt_verifier/gcp_jwt_verifier.circom
Replaces plaintext eat_nonce_0_b64_output and image_hash outputs with packed byte representations using PackBytes; introduces EAT_NONCE_PACKED_CHUNKS and IMAGE_HASH_PACKED_CHUNKS constants; adds packing logic for extracted values and updates validation flow to reference packed outputs.
Preprocessing logic
circuits/circuits/gcp_jwt_verifier/prepare.ts
Removes eat_nonce[0] decoding/verification; introduces eat_nonce[1] extraction and processing from JWT payload including validation against length constraints and character code array construction; extends circuit inputs with eat_nonce[1] metadata.
JSON field extraction
circuits/circuits/utils/gcp_jwt/verifyJSONFieldExtraction.circom
Replaces space-after-colon handling with quote-after-colon parsing; introduces value_start signal for position tracking; updates trailing validation to accept either closing bracket or comma after quoted values; refines constraint logic for JSON structure parsing.
Test configuration
circuits/package.json
Adds test-gcp-jwt-verifier npm script for running GCP JWT verifier tests.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Areas requiring extra attention:

  • verifyJSONFieldExtraction.circom — The constraint logic changes for quote handling and dual-path termination (bracket or comma) require careful verification against expected JSON structures to ensure no edge cases are missed.
  • gcp_jwt_verifier.circom — Validate that PackBytes integration correctly transforms output dimensions and that downstream consumers of these outputs are compatible with the new packed format.
  • prepare.ts — Ensure eat_nonce[1] extraction logic robustly handles malformed payloads and that the character code array construction aligns with circuit expectations.

Possibly related PRs

Suggested reviewers

  • remicolin

Poem

🔐 Bytes now dance in packed arrays tight,
Nonces multiply to double-light,
JSON quotes find their rightful place,
Colons and brackets in perfect grace,
Circuits humming in rhythm true. ✨

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/jwt-output

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2485ab1 and 32a9dc7.

📒 Files selected for processing (4)
  • circuits/circuits/gcp_jwt_verifier/gcp_jwt_verifier.circom (7 hunks)
  • circuits/circuits/gcp_jwt_verifier/prepare.ts (2 hunks)
  • circuits/circuits/utils/gcp_jwt/verifyJSONFieldExtraction.circom (1 hunks)
  • circuits/package.json (1 hunks)

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

// https://cloud.google.com/confidential-computing/confidential-space/docs/connect-external-resources
// EAT nonce (payload.eat_nonce[0])
var MAX_EAT_NONCE_B64_LENGTH = 99; // Max length for base64url string (74 bytes decoded = 99 b64url chars)
var MAX_EAT_NONCE_B64_LENGTH = 74; // Max length for base64url string (74 bytes decoded = 99 b64url chars)
Copy link

Choose a reason for hiding this comment

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

Bug: Incorrect base64 length constant truncates valid nonces

The MAX_EAT_NONCE_B64_LENGTH was changed from 99 to 74, but the variable represents base64url character length, not decoded byte length. The comment even states "74 bytes decoded = 99 b64url chars". This causes the circuit to reject valid nonces with base64 lengths between 75-99 characters. The prepare.ts file still uses 99, creating an inconsistency. The length check at line 167 and the ExtractAndVerifyJSONField template instantiation will fail for full-length nonces that are valid per the GCP spec.

Additional Locations (1)

Fix in Cursor Fix in Web

component is_value_after_quote = IsEqual();
is_value_after_quote.in[0] <== char_at_plus2;
is_value_after_quote.in[1] <== value_start;
is_quote.out * (1 - is_value_after_quote.out) === 0;
Copy link

Choose a reason for hiding this comment

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

Bug: Missing value_offset constraint allows arbitrary value extraction

The constraint value_offset === expected_value_offset was removed, which previously enforced that the extracted value position matched the expected location relative to the verified key. For the array format (:["value"]), there's now no constraint linking value_offset to the key position. A malicious prover could provide a key_offset pointing to the correct key while using a value_offset pointing to a different valid-looking value elsewhere in the JSON, effectively extracting an unintended value while passing verification.

Fix in Cursor Fix in Web


const eatNonce1Base64url = payload.eat_nonce[1];
console.log(`[INFO] eat_nonce[1] (base64url): ${eatNonce1Base64url}`);
console.log(`[INFO] eat_nonce[1] string length: ${eatNonce1Base64url.length} characters`);
Copy link

Choose a reason for hiding this comment

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

Bug: Missing array length check before accessing second nonce

The code accesses payload.eat_nonce[1] at line 284 without verifying the array has at least 2 elements. The existing validation at line 240 only checks payload.eat_nonce.length === 0, not length < 2. If a JWT contains only one nonce in the eat_nonce array, eatNonce1Base64url will be undefined, and accessing .length on line 286 will throw a TypeError and crash the preparation script.

Fix in Cursor Fix in Web

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.

2 participants