Skip to content

fix(runtime): enforce canonical base64url in agent_manifest and reject duplicate JSON keys across server, catalog, and inspection #798

Closed

Description

@drk-ram

What is wrong

In agentrust-io/cmcp on main, three verification and JSON/encoding boundary bugs exist in src/cmcp_runtime/:

  1. cmcp_runtime/agent_manifest.py::_b64url_decode accepts non-canonical base64url strings:

    • In src/cmcp_runtime/agent_manifest.py:85-91, _b64url_decode checks _B64URL_RE (^[A-Za-z0-9\-_]*$) and calls base64.urlsafe_b64decode without rejecting len(value) % 4 == 1 or verifying that re-encoding produces the identical unpadded string (base64.urlsafe_b64encode(raw).rstrip(b"=").decode("ascii") == value). Non-zero trailing bits in the final base64url character are silently ignored, allowing multiple string representations for the same key or signature bytes.
  2. Duplicate JSON object keys are accepted across mcp/server.py, catalog/loader.py, agent_manifest.py, and inspection/pipeline.py:

    • src/cmcp_runtime/mcp/server.py:556, src/cmcp_runtime/catalog/loader.py:245, src/cmcp_runtime/agent_manifest.py:136, and src/cmcp_runtime/inspection/pipeline.py:117, 267 call json.loads(...) without an object_pairs_hook to reject duplicate object member names.
    • An MCP JSON-RPC request or upstream response carrying duplicate keys (e.g., {"name": "safe", "name": "dangerous"} or duplicate "result" members) is silently collapsed to the last key by Python while downstream or upstream parsers reading the first key see a different tool or payload.
  3. mcp/proxy.py converts floats to strings in Cedar context construction instead of rejecting non-integer / out-of-range numbers:

    • In src/cmcp_runtime/mcp/proxy.py:187-204, isinstance(value, float) converts floats to str(value) (including NaN/Infinity if reached in-memory), and integers outside the RFC 8785 safe-integer range ([-9007199254740991, 9007199254740991]) are not rejected before JCS canonicalization in TRACE action hashing.

Expected behavior

  1. Enforce canonical unpadded base64url (rejecting len % 4 == 1 and non-zero trailing bits via round-trip check) in src/cmcp_runtime/agent_manifest.py::_b64url_decode.
  2. Reject duplicate JSON object member names via object_pairs_hook in mcp/server.py, catalog/loader.py, agent_manifest.py, and inspection/pipeline.py.
  3. Validate integer bounds and reject non-finite floats in mcp/proxy.py.

Activity

  1. github-actions commented on Oct 23, 2026

    @github-actions
    Contributor

    🟡 Contributor Check: MEDIUM

    Check Result
    Profile MEDIUM
    Credential LOW
    Overall MEDIUM

    Automated check by AgenTrust Contributor Check.

  2. rajnisht7 commented on Oct 23, 2026

    @rajnisht7
    Member

    /vouch

  3. github-actions commented on Oct 23, 2026

    @github-actions
    Contributor

    Usage: /vouch @username, one account per comment.

  4. rajnisht7 commented on Oct 23, 2026

    @rajnisht7
    Member

    /vouch @drk-ram

  5. github-actions commented on Oct 23, 2026

    @github-actions
    Contributor

    @drk-ram is vouched by @rajnisht7. Pull requests from that account will not be closed by the vouch check.

  6. added a commit that references this issue on Oct 23, 2026
  7. added a commit that references this issue on Oct 29, 2026
    31fdb56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions