From 2411f8f33811a9afdd63cfe80968527330d8c483 Mon Sep 17 00:00:00 2001 From: Srinivasa Consultants <78673153+dinakarjs@users.noreply.github.com> Date: Sun, 25 Oct 2026 03:30:02 +0530 Subject: [PATCH] fix: reject malformed present agent identity Signed-off-by: Srinivasa Consultants <78673153+dinakarjs@users.noreply.github.com> --- src/cmcp_verify/embodied_action.py | 5 ++++- tests/unit/test_embodied_action_evidence.py | 14 +++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/cmcp_verify/embodied_action.py b/src/cmcp_verify/embodied_action.py index 2222f861..0f94af2f 100644 --- a/src/cmcp_verify/embodied_action.py +++ b/src/cmcp_verify/embodied_action.py @@ -279,7 +279,10 @@ def verify_embodied_action_evidence( verified_fields.append("tool_catalog_hash") agent_id = _claim_agent_id(claim_json) - if agent_id is not None: + gateway = claim_json.get("gateway") + if isinstance(gateway, dict) and "agent_identity" in gateway and not agent_id: + failures.append("claim_json.gateway.agent_identity.agent_id must be a non-empty string") + elif agent_id is not None: if detached_payload.get("agent_id") != agent_id: failures.append("agent_id does not match TRACE Claim agent identity") else: diff --git a/tests/unit/test_embodied_action_evidence.py b/tests/unit/test_embodied_action_evidence.py index 378fc88e..3bde382c 100644 --- a/tests/unit/test_embodied_action_evidence.py +++ b/tests/unit/test_embodied_action_evidence.py @@ -291,13 +291,21 @@ def test_agent_identity_mismatch_fails(): assert any("agent_id" in failure for failure in result.failures) -def test_non_object_agent_identity_is_ignored(): +@pytest.mark.parametrize("identity", [None, {}, {"agent_id": 42}, {"agent_id": ""}, "not-an-object"]) +def test_malformed_present_agent_identity_fails(identity): fixture = copy.deepcopy(_fixture()) - fixture["trace_claim"]["gateway"]["agent_identity"] = "not-an-object" - + fixture["trace_claim"]["gateway"]["agent_identity"] = identity result = _verify_fixture(fixture) + assert not result.verified + assert any("agent_identity.agent_id" in failure for failure in result.failures) + +def test_absent_agent_identity_keeps_optional_binding(): + fixture = copy.deepcopy(_fixture()) + fixture["trace_claim"]["gateway"].pop("agent_identity", None) + result = _verify_fixture(fixture) assert result.verified, result.failures + assert "agent_id" not in result.verified_fields def test_ros2_must_be_object_when_present():