From fce28fdcee53ce052a580b81c35f58a934079cef Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Thu, 20 Aug 2026 19:19:45 -0700 Subject: [PATCH] docs: check the shared platform-state caveat against trace-spec The SEV-SNP platform-state caveat here is verbatim with trace-spec and ca2a apart from one sentence. Nothing linked the three, so a change in one, such as agent-manifest shipping appraise_platform_info() on 2026-08-20, reaches the others only if someone remembers. - Wraps the shared prose in shared:platform-state-appraisal markers and moves the cMCP-specific sentence below the end marker. - Adds a limitations-parity workflow that fetches trace-spec's copy and fails on drift, on push, on PR and daily. Same shape as the schema-parity check on the apex site. Only the marked block is compared; the paragraph after it is this project's own. The full text stays here rather than becoming a link. LIMITATIONS.md exists to state the bounds where a reader meets them. Also publishes the file. cMCP was the only sibling whose Limitations nav entry left the docs site for a GitHub blob; it now renders at /limitations/ through a snippet include, the way agent-manifest does. Three links inside it were repo-relative, which cannot resolve both on GitHub and at /limitations/, so they point at the published pages. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_013EQx4N5BzTQbY8kvXUsdkY --- .github/workflows/limitations-parity.yml | 75 ++++++++++++++++++++++++ LIMITATIONS.md | 23 ++++++-- docs/index.md | 2 +- docs/limitations.md | 1 + mkdocs.yml | 6 +- 5 files changed, 98 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/limitations-parity.yml create mode 100644 docs/limitations.md diff --git a/.github/workflows/limitations-parity.yml b/.github/workflows/limitations-parity.yml new file mode 100644 index 0000000..ca8ec9c --- /dev/null +++ b/.github/workflows/limitations-parity.yml @@ -0,0 +1,75 @@ +name: Limitations parity + +# The SEV-SNP platform-state caveat in LIMITATIONS.md is shared verbatim with +# agentrust-io/trace-spec and agentrust-io/ca2a, because the gap it describes is a +# property of the shared TEE provider layer rather than of any one project. Three +# hand-maintained copies of a security caveat drift, and the copy that goes stale +# is the one that quietly overstates what the project checks. +# +# The full text stays in this file on purpose: LIMITATIONS.md exists to state the +# bounds where a reader will actually meet them, not to send them somewhere else. +# This job keeps the copies honest instead of thinning them out. +# +# Same shape as the schema-parity check in agentrust-io/agentrust-io.github.io. +# Only the text between the markers is compared. The project-specific paragraph +# after the end marker is this repository's own. + +on: + push: + branches: [main] + paths: ['LIMITATIONS.md', '.github/workflows/limitations-parity.yml'] + pull_request: + paths: ['LIMITATIONS.md', '.github/workflows/limitations-parity.yml'] + schedule: + # trace-spec can change without anything happening here, so also check daily. + - cron: '41 6 * * *' + workflow_dispatch: + +permissions: + contents: read + +jobs: + parity: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Compare the shared block with trace-spec + run: | + set -euo pipefail + src=https://raw.githubusercontent.com/agentrust-io/trace-spec/main/LIMITATIONS.md + begin='' + end='' + + extract() { + awk -v b="$begin" -v e="$end" ' + index($0, b) { grab = 1; next } + index($0, e) { grab = 0 } + grab { print } + ' "$1" + } + + if ! curl -fsSL "$src" -o /tmp/upstream.md; then + echo "::error::could not fetch $src" + exit 1 + fi + + extract LIMITATIONS.md > /tmp/local.txt + extract /tmp/upstream.md > /tmp/remote.txt + + if [ ! -s /tmp/local.txt ]; then + echo "::error::LIMITATIONS.md has no shared:platform-state-appraisal block" + exit 1 + fi + if [ ! -s /tmp/remote.txt ]; then + echo "::error::trace-spec/LIMITATIONS.md has no shared:platform-state-appraisal block" + exit 1 + fi + + if diff -u /tmp/remote.txt /tmp/local.txt; then + echo "ok shared block matches trace-spec" + else + echo "::error::the shared block has drifted from trace-spec/LIMITATIONS.md." + echo "::error::Edit it in trace-spec first, then copy the block here." + exit 1 + fi diff --git a/LIMITATIONS.md b/LIMITATIONS.md index fd00752..950dc0f 100644 --- a/LIMITATIONS.md +++ b/LIMITATIONS.md @@ -8,7 +8,7 @@ This document describes what cMCP does not prevent, where its guarantees end, an Cedar policy evaluation is only as correct as the policy the operator wrote and approved. cMCP measures the policy bundle hash into the TEE attestation report, which proves the policy that ran is the policy that was approved. It does not evaluate whether that policy achieves the intended security outcome. A policy that contains `permit(principal, action, resource);` without conditions permits every tool call. Policy correctness is the operator's responsibility; policy review is a separate control. **Compromised TEE firmware or microcode** -Hardware attestation proves the workload hash was measured in silicon. It does not protect against vulnerabilities in the TEE firmware or CPU microcode itself (Spectre-class side channels, cache timing, power analysis, fault injection targeting the TEE boundary). Protection at this level is the responsibility of the hardware vendor. Operators must keep TEE firmware and microcode up to date; see [Compensating Controls](docs/spec/threat-model.md#compensating-controls-operator-responsibilities) in the threat model. +Hardware attestation proves the workload hash was measured in silicon. It does not protect against vulnerabilities in the TEE firmware or CPU microcode itself (Spectre-class side channels, cache timing, power analysis, fault injection targeting the TEE boundary). Protection at this level is the responsibility of the hardware vendor. Operators must keep TEE firmware and microcode up to date; see [Compensating Controls](https://cmcp.agentrust-io.com/spec/threat-model/#compensating-controls-operator-responsibilities) in the threat model. **Azure confidential VMs: attestation is vTPM-rooted, one hop longer** On Azure confidential VMs (`AzureCVMProvider`), SEV-SNP runs behind a Hyper-V paravisor: there is no `/dev/sev-guest`, and the guest cannot write the SNP `REPORT_DATA` field (the paravisor sets it to `sha256(runtime_data)`, binding the vTPM attestation key). cMCP therefore does not bind its key/audit-root directly into the SNP report on Azure. Instead it commits the nonce into an AK-signed TPM quote, and the SNP report (verified via the VCEK→ASK→ARK chain) attests that the AK is genuine SNP silicon. The trust root is still AMD, but the chain is one hop longer than direct-silicon binding, and it additionally trusts the paravisor's binding of the vTPM AK into `REPORT_DATA`. Bare-metal / non-paravisor SNP guests (`SEVSNPProvider`) bind directly into the report and do not add this hop. @@ -46,7 +46,7 @@ When configured, cMCP verifies a signed Agent Manifest against a trusted issuer cMCP intercepts tool calls at the MCP protocol boundary. It does not observe or modify LLM inference, the contents of the agent's context window, or model outputs that do not produce a tool call. A model could hallucinate a response, leak sensitive context in a chat reply, or receive a poisoned tool response that influences subsequent reasoning -- none of these are visible to the gateway. cMCP controls the tool boundary, not the model boundary. **Response injection evasion via novel patterns** -The response inspector uses pattern-based detection for prompt injection in tool responses. Pattern-based detection has false negatives. A sufficiently sophisticated injection may evade the current pattern list. The pattern list must be maintained and updated by the operator as new injection techniques emerge; see [Compensating Controls](docs/spec/threat-model.md#compensating-controls-operator-responsibilities). +The response inspector uses pattern-based detection for prompt injection in tool responses. Pattern-based detection has false negatives. A sufficiently sophisticated injection may evade the current pattern list. The pattern list must be maintained and updated by the operator as new injection techniques emerge; see [Compensating Controls](https://cmcp.agentrust-io.com/spec/threat-model/#compensating-controls-operator-responsibilities). **APM and telemetry payload capture** The TEE prevents plaintext from leaving the enclave to any destination not covered by the egress policy. This protection is structural only when the egress policy explicitly denies APM and telemetry endpoints. If the operator allowlists those endpoints in the Cedar policy, the TEE boundary does not prevent payload capture by the APM agent. A TRACE Claim with an egress policy that permits APM or SDK telemetry endpoints does not provide this protection. Verifiers must inspect the policy bundle hash and confirm the policy excludes those endpoints. @@ -60,7 +60,7 @@ The catalog binds each tool name to a specific upstream server identity, which p - **No hardware root of trust.** The signing key is held in software and is accessible to any process running as the same user. A privileged operator can extract it. - **No verifiable measurement.** The `trace.runtime.measurement` field is all zeros in dev mode. There is no hardware-measured enclave identity, so a verifier cannot confirm which binary ran. -- **Threat classes T1 through T4 are not covered.** These are the rogue administrator, host OS compromise, post-incident audit log reconstruction, and policy substitution threats described in the [threat model](docs/spec/threat-model.md). All four require a hardware TEE to close. In software-only mode, all four remain open. +- **Threat classes T1 through T4 are not covered.** These are the rogue administrator, host OS compromise, post-incident audit log reconstruction, and policy substitution threats described in the [threat model](https://cmcp.agentrust-io.com/spec/threat-model/). All four require a hardware TEE to close. In software-only mode, all four remain open. - **TRACE Claims are partially verified only.** The `cmcp_verify` library returns `status: partially_verified` and reports `hardware_attestation: software-only mode -- not hardware-backed`. Claims produced in dev mode must not be presented as hardware-attested proof to auditors or regulators. ## What attestation verification establishes, and what it does not @@ -99,6 +99,12 @@ Two gaps are worth stating plainly for the TPM path: ## Platform state is not appraised + + + The SEV-SNP path here establishes that a report is authentic and which workload it describes: report signature, the VCEK to ASK to ARK chain with the ARK pinned by the operator, and measurement binding. Those are the right four checks and they are not @@ -108,17 +114,22 @@ in dispute. report carries that separately in `PLATFORM_INFO` at offset 0x40: whether SMT is on, whether ECC is enabled, whether ciphertext hiding is enforced, and whether the firmware completed its boot-time DRAM alias check, which is AMD's mitigation for -BadRAM (security bulletin SB-3015). `agent-manifest` parses and can appraise these fields as of 2026-08-20; cMCP does not yet call that appraisal. +BadRAM (security bulletin SB-3015). The practical consequence: a report from a machine with SMT enabled and the alias check never completed verifies exactly as cleanly as one from a machine with neither condition. If that distinction matters to your deployment, it has to be asserted -explicitly, and today cMCP does not assert it for you. +explicitly. Related: [google/go-sev-guest#195](https://github.com/google/go-sev-guest/issues/195), where the reference verifier's own platform-info policy field is documented as a ceiling while four of its seven fields are enforced as minimums. Worth reading before writing any policy over these bits. + + +**In cMCP.** [`agent-manifest`](https://manifest.agentrust-io.com/limitations/) parses these fields and can +enforce a policy over them as of 2026-08-20. cMCP does not yet call that appraisal, so +cMCP does not assert it for you. ## What cMCP does not do @@ -167,4 +178,4 @@ Expected component breakdown for a 10-rule policy bundle: | Audit entry hash computation | approximately 0.1ms | | Network routing overhead | 0.5 to 2ms | -These are targets from [docs/testing/benchmarks.md](docs/testing/benchmarks.md). Actual results on real TEE hardware will vary by provider and payload size; benchmark results are committed per provider to `benchmarks/` in CI. +These are targets from [the benchmark methodology](https://cmcp.agentrust-io.com/testing/benchmarks/). Actual results on real TEE hardware will vary by provider and payload size; benchmark results are committed per provider to `benchmarks/` in CI. diff --git a/docs/index.md b/docs/index.md index 0bdc6ab..66d4210 100644 --- a/docs/index.md +++ b/docs/index.md @@ -61,7 +61,7 @@ cMCP moves the decision and the evidence inside a TEE. The policy bundle is meas What is attested against real silicon, what is parsed, and what is not appraised at all. - [Limitations](https://github.com/agentrust-io/cmcp/blob/main/LIMITATIONS.md) + [Limitations](limitations.md) diff --git a/docs/limitations.md b/docs/limitations.md new file mode 100644 index 0000000..2d9146d --- /dev/null +++ b/docs/limitations.md @@ -0,0 +1 @@ +--8<-- "LIMITATIONS.md" diff --git a/mkdocs.yml b/mkdocs.yml index b3265ed..97392ba 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -126,7 +126,9 @@ markdown_extensions: - pymdownx.highlight: anchor_linenums: true - pymdownx.inlinehilite - - pymdownx.snippets + - pymdownx.snippets: + base_path: ["."] + check_paths: true - pymdownx.emoji: emoji_index: !!python/name:material.extensions.emoji.twemoji emoji_generator: !!python/name:material.extensions.emoji.to_svg @@ -195,7 +197,7 @@ nav: - Soak Test: testing/soak-test.md - Hardware Validation: testing/hardware-validation.md - Project: - - Limitations: https://github.com/agentrust-io/cmcp/blob/main/LIMITATIONS.md + - Limitations: limitations.md - Changelog: https://github.com/agentrust-io/cmcp/blob/main/CHANGELOG.md - Contributing: https://github.com/agentrust-io/cmcp/blob/main/CONTRIBUTING.md - Governance: https://github.com/agentrust-io/cmcp/blob/main/GOVERNANCE.md