Skip to content

fix(examples): reject duplicate JSON keys, non-finite numbers, and boolean sequences in verify_receipts and verify_purchase (#369) - #373

Open
drk-ram wants to merge 1 commit into
agentrust-io:mainfrom
drk-ram:drk-ram-fix-examples-369
Open

drk-ram wants to merge 1 commit into
agentrust-io:mainfrom
drk-ram:drk-ram-fix-examples-369

Conversation

@drk-ram

@drk-ram drk-ram commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Reject duplicate JSON object keys and NaN/Infinity constants, pass allow_nan=False, and require type(receipt["sequence"]) is int in examples/embodied-action-receipts/verify_receipts.py.
  • Guard non-dict sections, enforce safe-integer bounds (<= 2**53 - 1) on amount_minor and max_amount_minor, and reject duplicate JSON keys and NaN/Infinity in examples/agentic-commerce-accountability/verify_purchase.py.

Closes #369

Validation

  • python -m pytest examples/embodied-action-receipts/tests/test_verify_receipts.py examples/agentic-commerce-accountability/tests/test_verify_purchase.py -q

@drk-ram
drk-ram requested review from a team, carloshvp and imran-siddique as code owners October 23, 2026 23:08
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

🟡 Contributor Check: MEDIUM

Check Result
Profile MEDIUM
Credential LOW
Overall MEDIUM

Automated check by AgenTrust Contributor Check.

@github-actions github-actions Bot added the needs-review:MEDIUM Contributor check flagged MEDIUM risk label Oct 23, 2026
@drk-ram
drk-ram force-pushed the drk-ram-fix-examples-369 branch from 2638393 to 6e60236 Compare October 23, 2026 23:09
carloshvp
carloshvp previously approved these changes Oct 24, 2026

@carloshvp carloshvp 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.

Reviewed exact head 6e60236cdde1a907e7430049c263b32bc1b17f0b in an isolated checkout.

The example verifiers now reject ambiguous/non-finite JSON, boolean receipt sequence numbers, malformed purchase sections and non-integer/out-of-range minor-unit amounts while preserving the existing signed receipt and purchase fixtures. These checks establish the example's evidence/structure contract, not physical completion.

Validation: 9 receipt tests with 12 subtests and 8 purchase tests with 9 subtests passed. The repository's actual hosted Ruff subset (integrations/packages/scripts/tests/claude-code/copilot/plugins/scheduled-agents/shadow-ai; E4,E7,E9,F) and diff whitespace checks passed. An additional optional lint of the example tree reports two pre-existing E402 imports after its sys.path setup; that is outside the hosted subset and is not introduced here. Sign-offs are present. No blocking source finding; hosted CI and maintainer policy remain separate.

Reviewed with OpenAI Codex.

@rajnisht7 rajnisht7 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.

the overall changes looks good, a few points needs to be addressed:

  1. verify_purchase.digest() is still missing allow_nan=False. Receipts side got it, purchase side did not. digest({"x": float("nan")}) currently succeeds and produces a hash. Programmatic path is not closed.

  2. The new duplicate-key test does not actually test duplicate keys. Fixture ends with }\n, so raw[:-1] + ', "extra": 1, "extra": 2}' produces malformed JSON (extra data), not a duplicate-key object. It never hits _unique_object.

Also missing tests for the new purchase behaviors (safe-integer bound, section guards, parser-level NaN/duplicate rejection).

@dinakarjs dinakarjs 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.

Source follow-up at 6e60236. The diff leaves verify_purchase.digest using json.dumps without allow_nan=False, while receipt canonicalization now rejects non-finite values. Please cover both programmatic and parsed-input paths, as Rajnish requested.

For the duplicate-key regression, first establish that the crafted string is syntactically valid JSON under the ordinary decoder, then require the strict verifier to reject it. A guard-removal control should make that same fixture reach the accepting path; a generic malformed verdict alone does not establish that _unique_object ran. Keep the boolean-sequence case separate.

Add independent purchase cases for malformed sections and safe-integer boundaries, with valid boundary twins, plus parser duplicate/non-finite cases. I inspected the diff and existing review; I did not rerun tests or mutations in this pass. Reviewed with OpenAI Codex.

…olean sequences in verify_receipts and verify_purchase (agentrust-io#369)

- Reject duplicate JSON object keys, NaN/Infinity constants, and float
  exponent overflow in examples/embodied-action-receipts/verify_receipts.py,
  pass allow_nan=False in canonical_bytes, and require integer receipt
  sequence numbers.
- Guard non-dict sections, enforce safe-integer bounds on amount_minor and
  max_amount_minor, pass allow_nan=False in digest, and reject duplicate
  JSON keys, NaN/Infinity constants, and float exponent overflow in
  examples/agentic-commerce-accountability/verify_purchase.py.

Closes agentrust-io#369

Signed-off-by: Raghuvar Karthik Durga <177662415+drk-ram@users.noreply.github.com>
@drk-ram

drk-ram commented Oct 29, 2026

Copy link
Copy Markdown
Contributor Author

@rajnisht7 @dinakarjs @carloshvp Rebased onto origin/main and updated at 4e003dc:

  1. verify_purchase.digest() programmatic allow_nan=False (examples/agentic-commerce-accountability/verify_purchase.py): Added allow_nan=False to digest(), added _loads_strict with _unique_object, _no_nonfinite_constant, and _finite_float (math.isfinite), and guarded digest comparisons with _matches_digest.
  2. Duplicate-key regression and separate boolean-sequence case (examples/embodied-action-receipts/tests/test_verify_receipts.py): Stripped trailing whitespace (raw.rstrip()[:-1] + ', "extra": 1, "extra": 2}'), verified that json.loads(dup) succeeds and passes verify_document when parsed leniently, and verified that verify_text(dup, trusted) rejects it with malformed via _unique_object. Kept test_boolean_sequence_is_rejected and test_nonfinite_json_and_canonical_bytes_are_rejected as separate test methods (11 passed).
  3. Independent purchase test coverage (examples/agentic-commerce-accountability/tests/test_verify_purchase.py): Added separate tests for test_digest_rejects_nonfinite_values, test_malformed_sections_are_rejected, test_safe_integer_boundaries (with valid boundary twins 9007199254740991 / 1 accepted and 9007199254740992 rejected on both amount_minor and max_amount_minor), and test_parser_rejects_duplicate_keys_and_nonfinite_json (12 passed).

@dinakarjs dinakarjs 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.

Re-reviewed exact head 4e003dc on Linux/Python 3.12.14.

The purchase digest now refuses non-finite programmatic values; strict parsing covers duplicate members, constants and exponent overflow. The receipt duplicate-key fixture is valid under the ordinary decoder and reaches the accepting document verifier before strict parsing refuses it, so the negative no longer relies on malformed syntax. Boolean sequence, purchase section shape and safe-integer boundary controls are separate. Fresh receipt hash-lock environment: 11 receipt unittest methods and 12 purchase unittest methods pass; whitespace passes. My earlier follow-up is addressed within these offline examples. No live-commerce, real-controller or production authorization assurance is claimed.

Reviewed with OpenAI Codex.

@carloshvp carloshvp 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.

Reviewed current head 4e003dc4da085467e82cc13b55d5a3ab59a6fcd9 in an isolated checkout.

Both fixture loaders reject duplicate JSON members, literal non-finite values and exponent overflow. Programmatic digest/canonical serialization refuses non-finite values; boolean receipt sequences are refused. The valid signed fixture remains accepted, while its duplicate-key twin is rejected before verification. Both example suites pass (12 commerce and 11 embodied cases), plus all 60 root tests.

The repository CI Ruff selection and whitespace checks pass; all PR commits carry DCO sign-offs. This approves the bounded software scope. Current-head hosted checks and maintainer requirements remain applicable.

Reviewed with OpenAI Codex.

This branch has not been deployed

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

Labels

needs-review:MEDIUM Contributor check flagged MEDIUM risk

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(examples): reject duplicate JSON keys, non-finite numbers, and boolean sequences in verify_receipts and verify_purchase

4 participants