Repository navigation
fix(verify): enforce canonical base64url and reject private JWK members in kill_switch and claim verification (#804) - #808
Conversation
|
🟡 Contributor Check: MEDIUM
Automated check by AgenTrust Contributor Check. |
carloshvp
left a comment
There was a problem hiding this comment.
Reviewed exact head c827a497a3c4d111b1de6c6926369f71276a28a8 in an isolated checkout.
I independently signed a valid claim, changed only unused signature pad bits while preserving the decoded signature bytes, and confirmed that this head rejects the alias while the actual merge-base verifier accepts it. The intact signed control passes. A claim freshly re-signed after adding private JWK material is also rejected here and accepted by the old verifier, so that check is not merely an invalid-signature test. The kill-switch required fields and canonical decoder are consistent with the changed contract.
Local hash-locked Python 3.12.10 checks: 2,526 unit tests passed, 20 skipped; pip check, Ruff, mypy and Bandit passed, and commit sign-offs are present. Please trim the extra blank line at test_kill_switch_evidence.py EOF. No blocking source finding; required hosted checks and maintainer approvals remain outstanding.
Reviewed with OpenAI Codex.
noah-ing
left a comment
There was a problem hiding this comment.
Reviewed exact head c827a497a3c4d111b1de6c6926369f71276a28a8. The implementation passed my independent signed Claim and refusal-receipt controls: intact signatures verified, noncanonical signature/key encodings and private JWK members were rejected, and empty required receipt fields failed. The local unit suite passed (2,526 passed, 20 skipped), along with Ruff, mypy, Bandit, and dependency consistency checks.
I am requesting a regression-test change before this security fix merges. The new claim_with_priv fixture has an invalid all-zero signature and no nonce. On the merge base, _verify_signature and _verify_key_binding already reject it, so the committed rejection assertions do not establish that this patch closes a previously accepted case. Please add a valid signed control, then test noncanonical signature and key encodings and private JWK members through the public Claim verifier; cover the new required receipt-field rules through verify_kill_switch_refusal as well. The source behaved correctly in my independent controls. Hosted CI remains blocked by the existing locked-dependency audit, and required maintainer gates are outstanding.
|
Thanks @noah-ing and @carloshvp! Updated |
|
Thanks for the follow-up. I reviewed head |
dinakarjs
left a comment
There was a problem hiding this comment.
I prepared a signed adoption companion addressing the outstanding review finding: dinakarjs#8
Validation: final unit+conformance+integration+confinement suite 2654 passed/29 skipped. Ruff src/tests, strict mypy and Bandit pass. Disabling only signature-path key canonicality makes the signature assertion fail; separately disabling only key-binding canonicality makes the binding assertion fail, retaining all test names. Both guard removals are reverted.
Please cherry-pick/adopt the companion and request independent re-review of the resulting head. I have contributed the follow-up and am not approving my own contribution.
|
Thanks @noah-ing! Updated |
|
Thanks @dinakarjs and @noah-ing! Adopted @dinakarjs's signed companion commit |
32e8a46 to
82707be
Compare
noah-ing
left a comment
There was a problem hiding this comment.
Reviewed exact head 82707bec6a927e0ea42843b77fd5e5b341bda418. The new key-alias regression re-signs the modified Claim, preserves the decoded key bytes and updates the nonce binding, so it now tests the intended canonical-encoding check. My independent signed control confirmed the old signature/key-binding paths accept that same-byte alias and this head rejects it; the intact signed control still passes those paths. Focused tests passed (80/80); the broader unit, conformance, integration and confinement suite passed (2,640 passed, 43 skipped). Ruff, changed-source mypy, dependency and whitespace checks passed. This resolves my prior requested change, so I approve this scoped verifier fix. The synthetic control is not a full hardware-attested Claim, and normal hosted checks still need to run under the repository gate.
carloshvp
left a comment
There was a problem hiding this comment.
Reviewed exact head 82707bec6a927e0ea42843b77fd5e5b341bda418 in an isolated checkout.
The runtime guards are unchanged from the earlier reviewed implementation; this head strengthens the committed end-to-end controls. They use freshly signed Claims/refusal receipts, same-byte noncanonical encoding aliases, re-signed private-JWK cases, bound JWK thumbprints and required receipt-field cases. Those controls and the full suite pass. No blocking source/test finding; the assertions distinguish signature/key binding from an overall hardware-attestation verdict.
Independent validation in a fresh repository-hash-locked Python 3.12.10 environment: 2,526 tests passed, 20 skipped; pip check, configured Ruff, mypy, Bandit and diff whitespace checks passed. Commit sign-offs are present. Hosted CI and applicable independent maintainer/security gates remain separate prerequisites to merge.
Reviewed with OpenAI Codex.
…rs in kill_switch and claim verification (agentrust-io#804) - Enforce canonical unpadded base64url in cmcp_verify.kill_switch._b64url_decode and require non-empty string agent_id, session_id, and refused_at on refusal receipts. - Reject RFC 7517/7518/8037 private or symmetric JWK parameters on trace.cnf.jwk and enforce canonical unpadded base64url on trace.cnf.jwk.x and signature in cmcp_verify.verify. Closes agentrust-io#804 Signed-off-by: Raghuvar Karthik Durga <177662415+drk-ram@users.noreply.github.com>
82707be to
4ab488a
Compare
What
Enforce canonical unpadded base64url and reject private JWK parameters in
cmcp_verify.kill_switchandcmcp_verify.verify.Why
Closes #804.
Security impact
Prevents malleable base64url keys/signatures in kill-switch refusal receipts and TRACE claims and rejects unredacted private key material (
d,p,q,dp,dq,qi,oth,k) intrace.cnf.jwk.Test plan
pytestpasses (pytest tests/unit/test_verify.py tests/unit/test_verify_malformed_claim_shapes.py -q)ruff checkpasses (ruff check src/cmcp_verify/kill_switch.py src/cmcp_verify/verify.py tests/unit/test_kill_switch_evidence.py)mypypasses (mypy src/cmcp_verify/kill_switch.py src/cmcp_verify/verify.py)DCO sign-off
Developer Certificate of Origin (https://developercertificate.org).