Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

prototype(verifier_token,execution_appraisal): enforce canonical 32-byte nonces, validate RelyingParty.challenge/verify_proof inputs, and reject non-finite JWT JSON

Open
#629 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@drk-ram is already working on this.

Since Oct 25, 2026.

  • #634 by @drk-ram — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Stale
Tech stack
python

Research direction

Start with the listed validation points in prototype/verifier_token.py, prototype/cmcp_gate.py, and prototype/execution_appraisal.py, then inspect the related nonce, challenge, proof, and token appraisal tests. Check how the code handles canonical nonces, exact integer ranges, and JSON constants. Done means all three boundaries enforce the stated constraints and the relevant tests cover the rejected inputs; pull request #634 is already open.

Written by the indexing model from the issue text.

Description

needs-review:MEDIUM
Summary

Three verification-boundary gaps exist in prototype/verifier_token.py, prototype/cmcp_gate.py, and prototype/execution_appraisal.py:

  1. Non-canonical 43-character base64url nonces accepted in Proof, RelyingParty.challenge, and CMCPTraceGate._prove (prototype/verifier_token.py lines 229, 770; prototype/cmcp_gate.py line 139):

    • Proof.nonce and RelyingParty.challenge check only r"^[A-Za-z0-9_-]{43}$" (and CMCPTraceGate._prove checks len(nonce) != 43) without verifying that the 43-character base64url string has zero unused trailing pad bits (_b64url(nonce) round-trip). As a result, "A" * 42 + "B" (non-zero pad bits) is accepted as a valid nonce.
  2. Unvalidated caller parameters in RelyingParty.challenge and verify_proof (prototype/verifier_token.py lines 730-780):

    • RelyingParty.challenge does not check isinstance(nonce, str) before re.fullmatch, does not validate session_id (Identifier) or action_digest (Digest), and does not require type(issued_at) is int and type(expires_at) is int with 0 <= issued_at < expires_at <= 9007199254740991 (allowing issued_at=False, expires_at=True or negative timestamps).
    • verify_proof does not check type(now) is int, type(challenge_issued_at) is int, or type(challenge_expires_at) is int (allowing now=True to satisfy 1 <= True < 2).
  3. Non-finite JSON constants and unbounded integer timestamps in prototype/execution_appraisal.py (lines 89-160):

    • authenticate_token parses JWT header and claims via json.loads(..., object_pairs_hook=_pairs) without parse_constant, allowing NaN / Infinity in JWT JSON, and appraise_launch does not bound iat, nbf, exp, and now by 9007199254740991 (JCS safe integer range).
Proposed Fix
  • Enforce canonical 32-byte base64url (_b64url(nonce)) on Proof.nonce, RelyingParty.challenge, and CMCPTraceGate._prove.
  • Validate session_id, action_digest, and exact integer timestamps (0 <= issued_at < expires_at <= 9007199254740991) in RelyingParty.challenge and verify_proof.
  • Reject non-finite JSON constants (parse_constant) in authenticate_token and bound iat, nbf, exp, and now by 9007199254740991 in appraise_launch.
Dominant language
Python
Stars
37
Forks
33
Avg merge
1d 10h
Merged PRs (30d)
112

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from agentrust-io/trace-spec

All issues in agentrust-io/trace-spec

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.