Repository navigation
Add Provenza: Agent Manifest issuer (composition-only, hybrid COSE) - #413
kironovlaziz-del wants to merge 2 commits into
Conversation
drk-ram
left a comment
There was a problem hiding this comment.
Reviewed head aefa2d93ed8a2e9906e4e0bf7df94e53afd9f977.
The sample is a real hybrid envelope. CBOR tag 98, two signature entries, protected alg -19 (Ed25519, 64-byte signature) and -49 (ML-DSA-65, 3309-byte signature). Against agent-manifest 0.15.0, python -m pytest integrations/provenza-agent-manifest/tests -q is 5 passed, 0 failed. Those tests pin the happy path. They do not pin the hybrid set the listing advertises.
main() returns 0 when the signatures verify, catalog_hash_matches is absent or true, and the verdict is VALID or INCOMPLETE (verify_provenza_manifest.py:98-99). verify_cose_manifest verifies every entry that is present. It does not require both families when crypto_profile is standard. In agent-manifest 0.15.0, PROFILE_REQUIRED_ALGORITHMS constrains only post-quantum, and only to ML-DSA-65. standard returns before any algorithm-set check. COSE_Sign entries are independent: the Ed25519 Sig_structure does not cover the sibling ML-DSA entry. I removed that sibling from the committed sample, kept the committed trusted keys, and verify_cose_manifest returned verified with one signer, algorithm -19. check() then reported signatures_verified: true, signers: 1, verdict: INCOMPLETE, catalog_hash_matches: true. That satisfies the exit-0 condition.
That is a downgrade, not an equivalent verification. draft-durga-pquip-pqc-agentic-delegation-00 treats hybrid Ed25519 + ML-DSA-65 as a conjunction. The classical component alone is not the hybrid signature, including in the case the classical key is the one that later fails. TR-2026-04 (10.5281/zenodo.23775532) states the same gate for a protocol reduction: dropping a required signer is not semantic equivalence. TR-2026-05 (10.5281/zenodo.23776217) is the identity side. An issuer claim the directory lists as hybrid is not established by the classical half. The README says the script checks both COSE signatures. It checks whatever signatures the file still carries.
Please refuse success unless the verified envelope contains both an Ed25519-family algorithm (-19, or the still-verified -8) and ML-DSA-65 (-49). A signers == 2 count is weaker than that if both entries could share a family; the SDK already rejects a repeated family, so the two-family predicate is the one that matches the claim. Add a regression that a one-entry envelope is rejected even when that one signature verifies against the supplied key. Please also stop test_cli_exit_codes from accepting either exit code. After 2027-01-31 the sample's verdict becomes EXPIRED and exit 0 would be wrong; a test that allows both will not catch a success-condition regression.
Non-blocking: the new workflow comments the checkout SHA as v4. The same SHA is labeled v7.0.1 in .github/workflows/validate.yml. The pin matches the repository; the comment does not.
I am not asking for a policy bundle, a hardware attestation, or a VALID verdict. Composition-only and INCOMPLETE are the right ceiling, and the README says so. That ceiling does not excuse a classical downgrade of the signature the listing advertises.
|
@drk-ram Thanks, agreed: one verified signer is not the hybrid signature. Fixed in the latest push: |
drk-ram
left a comment
There was a problem hiding this comment.
Reviewed head 13ef3e051b0b13a862164b187c66e39e32ef2e9d. Approving the follow-up: the signature-family downgrade and time-dependent exit-code checks from my earlier review are resolved.
The success predicate now uses verified algorithms, not the number of entries. The Ed25519 family (-19 or -8) and ML-DSA-65 (-49) are a conjunction; neither can substitute for the other. I verified the committed tag-98 envelope with its committed trust keys: two valid signatures, algorithms [-49, -19], matching tool-catalog root, composition-only INCOMPLETE, exit 0 within the validity window.
I independently removed each sibling signature without changing the remaining signature or payload. Both remaining signatures still verified and the verdict stayed INCOMPLETE, but the CLI returned 1: removing -49 produced missing_signers: ["ml-dsa-65"]; removing -19 produced ["ed25519"]. That directly closes the downgrade, rather than merely rejecting an invalid envelope.
I also created a genuinely signed -8 Ed25519 entry with a fresh test key while retaining the sample's unchanged ML-DSA signature. The hybrid passed; the valid -8 entry alone and a valid EdDSA COSE_Sign1 both failed with the missing ML-DSA family. Changing the protected algorithm without re-signing, corrupting either signature, and duplicating the classical family all failed. No cryptographic verification was replaced for these checks.
At 2026-12-01T00:00:00Z the complete envelope returned 0; at 2027-02-01T00:00:00Z it returned 1 with EXPIRED. The committed tests fix the verification clock and assert one exit code each. The README now states the conjunction and the single-signer refusal; the checkout comment identifies the pinned commit as v7.0.1.
Validation: Python 3.11.9 on Windows, agent-manifest 0.15.0, cryptography 50.0.2 / OpenSSL 4.0.3. python -m pytest integrations/provenza-agent-manifest/tests -q: 8 passed, 0 failed, 0 skipped. Additional independent signature/CLI controls: 11 passed, 0 failed. The initial local backend lacked ML-DSA support (3 passed, 5 failed); the final counts above are after installing a capable backend, not a fallback to classical verification. I did not run the hosted Python/version matrix.
The composition-only ceiling is unchanged. An authentic partial manifest is not a complete attestation, and the externally supplied trust keys remain the trust anchor. No remaining security blocker found in this follow-up.
|
@drk-ram Thanks for the thorough independent re-check, especially the -8 and single-signer controls. |
Adds Provenza as an Agent Manifest issuer: a composition-only v0.2 manifest per governed agent, signed as a hybrid Ed25519 + ML-DSA-65 COSE_Sign, binding the approved MCP tool catalog and the audit-log root. The directory verifies a sample manifest offline with the released agent-manifest 0.15.0; reproduction steps are in the README. Requesting the community tier.