hardening: serialise the deploy payload once; guard/parser differential test; 0.6.3 - #11
Merged
Merged
Conversation
…bytes deploy_model serialises tx_data once, runs the share guard on json.loads of that payload, and sends the same payload (_send_transaction accepts a pre-serialised JSON string). The guard now judges exactly what is sent. Before, it walked the live objects, and json.dumps could serialise something different (for example a dict subclass with overridden item access). deploy_model is the only send path that runs the guard. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Generates 40k near-hex strings from a fixed seed: canonical hex, perturbed hex and free-form near-hex, with ASCII and Unicode whitespace, junk characters and 0x/0X prefixes. It asserts that (1) parse_share_y agrees with a reference strict grammar, and (2) the guard refuses every input that the strict reference, bytes.fromhex or the legacy truncating JS decoder turns into >= 16 bytes. Reverting the guard to the earlier canonical-only regex fails it (3 failures), and so does a lenient parser (1 failure). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
0.6.2 is published, so this change set ships as 0.6.3. CHANGELOG entry added. Not published: releasing is the owner's call. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
SaulBuilds
force-pushed
the
fix/pba-r2-sdk-serialise-once
branch
from
September 26, 2026 01:26
9df644d to
f4d834a
Compare
…ped share values - assert_payload_has_no_key_share_material parses the serialised payload with a hook that refuses duplicate object keys, then runs the guard. deploy_model uses it on the exact payload it sends. - The guard's nested JSON-string scan uses the same strict parse. - The share-shape match recognises bytes and their JSON renderings: integer lists, the Buffer JSON shape, and objects keyed 0..n-1 with byte values (>= 16 bytes). - The shared vectors file is v2 (byte shapes and raw payloads), byte-identical in citrate-sdk-js (sha256 pinned). - The differential tests cover y as bytes, bytearray, integer lists and the JSON byte shapes, plus duplicate keys. - The deploy payload test is renamed to test_payload_guard.py, with neutral case names. Hand mutants (6) are all killed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up hardening. Details are in the private audit record.
deploy_modelcallsjson.dumps(tx_data)once, runsassert_payload_has_no_key_share_materialon that payload (duplicate keys refused), and sends that same payload._send_transactionaccepts a pre-serialised string. This is the only send path that runs the guard.tests/test_payload_guard.pyparse_share_ymust agree with a reference strict grammar, and the guard must refuse everything the strict reference,bytes.fromhexor the legacy truncating decoder turns into 16 or more bytes.tests/test_guard_parser_differential.pyLocal CI, frozen lockfile, Python 3.11.16:
uv lock --checkand the locked pip-audit are clean.🤖 Generated with [Claude Code](https://claude.com/cla### Update (verifier round 5)
Verification
test_10year_medium_under_60s), on a machine at load average ~240; outside economics the count is 737 passed, 43 skipped.uv lock --check, the locked pip-audit and the wheel tripwire are clean.ude-code)