From 7845f958b8844afdd0cbb852166b572c0e85b6fa Mon Sep 17 00:00:00 2001 From: Imran Siddique Date: Sun, 7 Jun 2026 14:08:08 -0700 Subject: [PATCH] fix(startup): reject unknown TEE provider names at startup (HW-001, closes #171) Add _VALID_PROVIDERS frozenset to startup.py and validate attestation_report.provider immediately after attestation succeeds. An unrecognised provider name calls _fatal() and exits 1 before the value can propagate into TRACE Claims or Cedar policy context. Co-Authored-By: Claude Sonnet 4.6 --- src/cmcp_gateway/startup.py | 25 +++++++++++++++++++++++++ tests/unit/test_startup.py | 22 +++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/cmcp_gateway/startup.py b/src/cmcp_gateway/startup.py index 27182115..c999d65e 100644 --- a/src/cmcp_gateway/startup.py +++ b/src/cmcp_gateway/startup.py @@ -25,6 +25,17 @@ logger = logging.getLogger(__name__) +# HW-001: allowlist of canonical TEE provider names that may appear in +# AttestationReport.provider. Mirrors the keys of _PROVIDER_MAP in +# audit/trace_claim.py — kept as a local constant to avoid a circular import. +_VALID_PROVIDERS: frozenset[str] = frozenset({ + "sev-snp", + "tdx", + "opaque", + "tpm", + "software-only", +}) + @dataclass class GatewayContext: @@ -110,6 +121,20 @@ def run_startup(config_path: str) -> GatewayContext: attestation_report.measurement[:16], ) + # HW-001: reject unknown provider strings before they can propagate into + # TRACE Claims or Cedar policy context. A custom or misconfigured provider + # could set an arbitrary value in provider_name(); validate here at the + # boundary rather than relying on downstream consumers to handle it. + if attestation_report.provider not in _VALID_PROVIDERS: + _fatal( + "ATTESTATION_PROVIDER_INVALID", + f"TEE provider returned unknown platform string '{attestation_report.provider}'. " + f"Allowed values: {sorted(_VALID_PROVIDERS)}.", + provider=attestation_report.provider, + action="startup_aborted", + ) + sys.exit(1) + # AUTH-001 (CRITICAL): require a bearer token in production to authenticate # inbound MCP calls. Without it, any network client can invoke any tool. if config.bearer_token is None and not config.dev_mode: diff --git a/tests/unit/test_startup.py b/tests/unit/test_startup.py index 83dc9aea..140cbab7 100644 --- a/tests/unit/test_startup.py +++ b/tests/unit/test_startup.py @@ -5,7 +5,7 @@ import json import os from pathlib import Path -from unittest.mock import patch +from unittest.mock import MagicMock, patch import pytest @@ -162,3 +162,23 @@ def test_startup_fails_when_catalog_hash_unset_and_not_dev_mode(tmp_path, monkey with patch.dict(os.environ, env, clear=True), pytest.raises(SystemExit) as exc_info: run_startup(str(config_path)) assert exc_info.value.code == 1 + + +def test_startup_fails_on_unknown_tee_provider_name(complete_setup): + """HW-001: a provider that returns an unknown platform string must cause exit 1. + + The mock bypasses AttestationReport.__post_init__ by returning a plain + MagicMock, simulating a custom or misconfigured provider that injects an + arbitrary string before the startup boundary check can catch it. + """ + fake_report = MagicMock() + fake_report.provider = "evil-custom-tee" + fake_report.measurement = "aabbcc" * 8 + + with patch( + "cmcp_gateway.tee.base.SoftwareOnlyProvider.get_attestation_report", + return_value=fake_report, + ), pytest.raises(SystemExit) as exc_info: + run_startup(complete_setup) + + assert exc_info.value.code == 1