Repository navigation
Conversation
Signed-off-by: Raghuvar Karthik Durga <177662415+drk-ram@users.noreply.github.com>
|
🔴 Contributor Check: HIGH
Automated check by AgenTrust Contributor Check. |
noah-ing
left a comment
There was a problem hiding this comment.
I reviewed current head f2e3c2ddf74202ce0136b742f50dcefb2b520d66. I am requesting changes for the catalog ordering issue inline and the authoring workflow below.
Update the copyable catalog hashing instructions. docs/tutorials/tool-catalog-authoring.md:109,165,182,276 still calculates definition and catalog hashes with json.dumps(..., ensure_ascii=True). The runtime now uses RFC 8785. With description = "Résumé records" in the minimal catalog, the documented definition calculation gives sha256:6571a651…, while load_catalog expects sha256:2c88dbe4… and rejects the catalog. After correcting the definition hash, using the tutorial's CMCP_CATALOG_HASH still raises CatalogHashMismatch (sha256:2f92b0b9… versus sha256:8074ec8c…). Please update all four snippets and the adjacent prose to the new canonical bytes, and exercise a non-ASCII example so the published deployment command remains usable.
Local validation on this head: the full unit suite passed (2,597 passed, 21 skipped); Ruff, mypy (77 source files), and Bandit passed. The hosted code-test, CodeQL, documentation, confinement, and fuzz jobs are currently action_required with no executed jobs; the green contributor/vouch checks are not code validation. The required maintainer approvals remain outstanding.
| sorted_entries = sorted(raw_entries, key=lambda e: e["tool_name"]) | ||
| canonical = json.dumps(sorted_entries, sort_keys=True, separators=(",", ":"), ensure_ascii=True) | ||
| return f"sha256:{_sha256_hex(canonical.encode())}" | ||
| return f"sha256:{_sha256_hex(rfc8785.dumps(sorted_entries))}" |
There was a problem hiding this comment.
Catalog hash interoperability: JCS preserves array element order; it does not define the preceding sort here. Python sorts tool_name by Unicode code point, while UTF-16 string ordering places supplementary-plane characters before high BMP characters. I passed two schema-valid entries named tool_\uff5a and tool_\U00010000 through load_catalog: this code produced sha256:fd502d32645bfb6a3173e049c2644f4b044365c23ca0e16082b3b37888cece50; ordering those same entries by UTF-16 code units and applying the same RFC 8785 serializer produced sha256:d73d69f2f715692a18e007a2ff5d641daee6c43ce7ad6e1dc856ec2ee4df7294. Both names are accepted by the schema and loader. docs/spec/attestation.md says only “lexicographic ascending,” and the new test has one entry, so cross-language implementations can disagree on a valid catalog. Please specify the exact tool_name comparison order, implement it consistently, and add a two-entry interoperability vector.
carloshvp
left a comment
There was a problem hiding this comment.
Reviewed commit f2e3c2ddf74202ce0136b742f50dcefb2b520d66.
I confirmed the catalog-authoring blocker already identified in the review and prepared a correction for all four executable hash snippets in docs/tutorials/tool-catalog-authoring.md.
Each snippet needs rfc8785.dumps(...) and must hash the returned bytes directly:
import hashlib
import rfc8785
canonical = rfc8785.dumps(approved_definition)
definition_hash = "sha256:" + hashlib.sha256(canonical).hexdigest()
sorted_entries = sorted(entries, key=lambda e: e["tool_name"])
catalog_hash = "sha256:" + hashlib.sha256(rfc8785.dumps(sorted_entries)).hexdigest()Update the definition helper, both catalog helpers, the deployment one-liner, and the adjacent canonicalization prose. I exercised all four corrected snippets with Résumé records and a schema containing minimum: 1e-7: their output agrees with load_catalog, including expected_hash validation. With the original snippets, definition validation and then the catalog pin both fail. The separately raised cross-language tool-name ordering decision remains outstanding; this snippet correction retains the current runtime order.
On the unmodified runtime head, 153 focused claim/catalog/session/kill-switch/verifier tests pass; Ruff, mypy (77 files), and configured Bandit pass in the isolated hash-locked environment. These tests do not resolve the tutorial and ordering blockers or replace the required hosted validation and security-path approvals.
|
Prepared an adoption proposal for the catalog-entry ordering decision, based on head Only The tests add a fixed two-entry hashing vector and a schema-valid loader/pin control using Local hash-locked Python 3.12 validation: 38 focused catalog tests passed; full unit suite 2,612 passed, eight skipped with proxy environment variables removed. The initial full run had nine SOCKS-proxy dependency errors, not a clean pass. Ruff, mypy over 64 runtime source files, configured Bandit, and whitespace checks passed. Bandit emitted nosec-comment warnings. No runtime source or dependency change is included. Your branch is unchanged. The patch is available for cherry-picking or adaptation, subject to maintainer acceptance of the ordering rule. This does not resolve the review by itself or establish hosted validation/independent approval. The four tutorial snippet corrections already prepared in #839 remain separate and still need coordinated adoption. No existing catalog-pin transition is authorized by this proposal. Prepared with OpenAI Codex; commit DCO signed. |
Document Unicode code-point entry order separately from JCS object-key order. Use RFC 8785 bytes in every tutorial hash snippet and verify them against a UTF-8 catalog containing non-ASCII text and a fractional schema bound. Decode catalog files explicitly as UTF-8 so the published workflow also works on Windows. Signed-off-by: Raghuvar Karthik Durga <177662415+drk-ram@users.noreply.github.com>
|
@noah-ing @carloshvp Addressed in f19cca5. Adopted @dinakarjs's code-point ordering specification and two-entry vectors, plus all four RFC 8785 tutorial snippets from #839. A regression executes every snippet with |
dinakarjs
left a comment
There was a problem hiding this comment.
Re-reviewed the adopted catalog follow-up at f19cca5. The runtime, specification, two-entry vectors and tutorial consistently sort catalog entries by Unicode code point before JCS serializes the array. The tutorial examples exercise UTF-8 input and agree with the pinned loader hashes. Locally, 340 catalog, TRACE, session and verifier tests passed, and ruff check src tests passed. This closes my adoption follow-up. Hosted workflows report action_required, and Noah and Carlos retain disposition of their reviews. Prepared with OpenAI Codex.
What
Canonicalize TRACE claim signing inputs, claim digests, and tool catalog/definition SHA-256 hashes with RFC 8785 (JCS) instead of Python JSON formatting. The review follow-up
f19cca5specifies Unicode code-point catalog-entry ordering, corrects all four authoring/deployment hash snippets, and explicitly reads catalogs as UTF-8 so non-ASCII examples also work on Windows.Why
Python JSON escaping and number formatting can disagree with RFC 8785. The old tutorial generated definition hashes and catalog pins that the updated runtime rejected for descriptions such as
Résumé recordsand schema bounds such asminimum: 1e-7.Closes #837.
Adopts the ordering documentation/vectors proposed in
dinakarjs/cmcp@03e1d7fand the four tutorial corrections from #839. Entry sorting remains the current Python Unicode code-point order, explicitly distinguished from JCS's UTF-16 object-member ordering; no existing-pin migration or bypass is authorized.Security impact
Restores RFC 8785 canonicalization across
cmcp_runtime.audit.trace_claim,cmcp_runtime.catalog.loader,cmcp_runtime.session.manager, andcmcp_verify, preventing cross-verifier signature and digest mismatches. Catalog files are decoded as UTF-8 independently of the host locale, and invalid UTF-8 is reported asConfigError.Test plan
pytestpasses —pytest tests/unit/test_catalog_jcs_hashes.py tests/unit/test_trace_claim.py tests/unit/test_session_manager.py --basetemp .council-validation\pytest -q: 85 passed.ruff checkpasses in the documented scope —ruff check src tests: passed with repository-locked Ruff 0.17.0. Unscopedruff checkreports 370 pre-existing findings, all in unchanged files outsidesrc/tests; this is not a clean repository-wide lint result.mypypasses —mypy src: no issues in 77 source files with repository-locked mypy 2.4.0. The initially installed mypy 1.18.2 reported an error in unchangedmcp/proxy.py; restoring the locked tool in an isolated project environment resolved that tooling mismatch.Additional automated validation:
pytest tests/unit/test_catalog.py tests/unit/test_catalog_canonical_json.py --basetemp .council-validation\catalog-extended -q: 48 passed.test_tutorial_hash_snippets_match_loaderexecutes all four published hash snippets withRésumé recordsandminimum: 1e-7, and checks the resulting definition hash and catalog pin againstload_catalog(..., expected_hash=...).bandit -r src -c pyproject.toml -q: passed (existing nosec-comment warnings).git diff --check: passed.Validation was local on Windows/Python 3.11.9. Hosted validation and renewed independent security-path reviews remain separate requirements.
DCO sign-off
Developer Certificate of Origin (https://developercertificate.org).