|
| 1 | +# M5 Control Matrix — Stronger Isolation Acceptance Criteria |
| 2 | + |
| 3 | +This matrix maps each M5 security control to its enforcing component, failure mode, test coverage, and audit evidence. A reviewer or operator can use this matrix to verify that every claimed control is actually implemented, tested, and observable. |
| 4 | + |
| 5 | +Last updated: 2026-03-14 |
| 6 | + |
| 7 | +## Control Matrix |
| 8 | + |
| 9 | +| # | Control | Enforcing Component | Failure Mode | Test Covering It | Audit Evidence | |
| 10 | +|---|---------|-------------------|--------------|-----------------|----------------| |
| 11 | +| 1 | Startup gating via TPM2 attestation | Runtime Attestor (:8505) | Service refuses to start; reports `attestation_failure` to Incident Recorder | `TestAttest_BadTPMState`, `TestChain_AttestationFailure_ContainmentDispatched` | `incident-recorder-audit.jsonl` entry class=attestation_failure | |
| 12 | +| 2 | Continuous file integrity monitoring | Integrity Monitor (:8510) | State transitions to `degraded`; reports violations to Incident Recorder | `TestScan_BaselineMismatch`, `TestChain_IntegrityViolation_FreezeAndDisable` | Baseline scan results + incident report with file paths/hashes | |
| 13 | +| 3 | Auto-containment on integrity violation | Incident Recorder (:8515) | freeze_agent + disable_airlock + force_vault_relock dispatched | `TestChain_IntegrityViolation_FreezeAndDisable`, `TestExecuteContainment_FreezeAgent` | Containment dispatch logs + target service acknowledgment | |
| 14 | +| 4 | Auto-containment on attestation failure | Incident Recorder (:8515) | freeze_agent + disable_airlock + force_vault_relock dispatched | `TestChain_AttestationFailure_ContainmentDispatched` | Incident record with state=contained | |
| 15 | +| 5 | Model quarantine on manifest mismatch | Incident Recorder (:8515) → Registry (:8470) | quarantine_model + freeze_agent dispatched | `TestChain_ManifestMismatch_QuarantinesModel` | POST to /api/v1/quarantine with model_path | |
| 16 | +| 6 | GPU runtime integrity verification | GPU Integrity Watch (:8495) | Warning/critical verdict triggers incident report | `TestProbe_DriverFingerprint`, `TestChain_GPUAnomaly_IncidentAndQuarantine` | GPU probe results + incident class=model_behavior_anomaly | |
| 17 | +| 7 | Centralised policy decisions (6 domains) | Policy Engine (:8500) | Allow/deny with structured evidence | `TestDecide_ToolAccess_*`, `TestDecide_AgentRisk_*` (37 tests) | PolicyDecision JSON with decision, reason, evidence | |
| 18 | +| 8 | Deny-by-default tool firewall | Tool Firewall (:8475) | Unknown tools denied | `TestEvaluate_*` (10 tests) | Audit log with tool name + decision | |
| 19 | +| 9 | Deny-by-default MCP firewall | MCP Firewall (:8496) | Unknown servers/tools denied; taint propagation; input redaction | `TestEvaluate_*`, `TestAdversarial_*` (44+ tests) | Hash-chained audit log + signed decision receipts | |
| 20 | +| 10 | HMAC-signed capability tokens | Agent (:8476) capabilities.py | Token verification: expiry, nonce replay, HMAC signature | `TestTokenSigning`, `test_stale_capability_token_rejected`, `test_replayed_capability_token_rejected` | Token ID in agent-audit.jsonl per step | |
| 21 | +| 11 | Two-phase approval for high-risk actions | Agent (:8476) policy.py | TRUST_CHANGE, EXPORT_DATA, WIDEN_SCOPE etc. always escalated to "ask" | `test_two_phase_actions_require_approval` | PolicyDecision with decision=ask for TWO_PHASE_ACTIONS | |
| 22 | +| 12 | Step signature validation | Agent sandbox.py | Step modified between planning and execution is rejected | `test_signed_step_verifies`, `test_tampered_step_fails_verification` | Step signature in audit trail | |
| 23 | +| 13 | Per-step capability re-validation | Agent sandbox.py | Path/tool/scope mutations caught at execution time | `test_path_mutation_caught_at_execution`, `test_tool_mutation_caught_at_execution` | Re-validation check in executor log | |
| 24 | +| 14 | Workspace hard walls | Agent sandbox.py WorkspaceGuard | Symlink escape, cross-workspace FD reuse, hardlink tricks detected | `test_symlink_traversal_blocked`, `test_workspace_id_spoofing_blocked` | Workspace violation log entry | |
| 25 | +| 15 | Storage gateway blocked paths | Agent storage.py | /etc/shadow, /etc/passwd, policy files, service tokens always blocked | `test_shadow_file_blocked`, `test_service_token_blocked` | Storage gateway deny in audit log | |
| 26 | +| 16 | Sensitivity ceiling enforcement | Agent policy.py + storage.py | Files exceeding sensitivity ceiling are blocked | `TestSensitivity_*` | Sensitivity classification in read result | |
| 27 | +| 17 | Recovery ceremony after containment | Incident Recorder recovery.go | Require ack + re-attestation before returning to trusted mode | `TestRecovery_CriticalRequiresReattestation` | Recovery requirement record with ack/reattest timestamps | |
| 28 | +| 18 | Latched degraded states | Incident Recorder recovery.go | attestation_failure, integrity_violation, unauthorized_access, manifest_mismatch remain latched | `TestLatchedClasses` | Incident state remains until manual review | |
| 29 | +| 19 | Severity escalation | Incident Recorder recovery.go | Repeated medium-severity events escalate per rules | `TestEscalation_RepeatedPromptInjection` | Escalated severity in incident record | |
| 30 | +| 20 | Forensic bundle export | Incident Recorder recovery.go | Signed export of incidents, audit, state, policy digest | `TestForensicBundle_ExportAndVerify`, `TestForensicBundle_TamperDetection` | Forensic bundle JSON with HMAC signature | |
| 31 | +| 21 | Service token propagation | Incident Recorder containment.go | Bearer token included in all containment HTTP calls | `TestChain_BearerToken_PropagatedToContainment` | Authorization header in containment requests | |
| 32 | +| 22 | HSM/TPM2 key management | Agent keystore.py | Software/TPM2/PKCS#11 backends with auto-detection | `TestKeystore_*` (31 tests) | Keystore provider name in agent startup log | |
| 33 | +| 23 | Prompt injection detection | MCP Firewall global rules | Shell metacharacters and prompt patterns detected and denied | `TestAdversarial_MalformedMCPPayload` | Global rule match in audit log | |
| 34 | +| 24 | MCP taint tracking | MCP Firewall taint.go | Session-scoped taint propagation prevents data flow violations | `TestAdversarial_TaintBypassAttempt`, `TestTaint_*` | Taint entries per session ID | |
| 35 | +| 25 | SBOM generation verification | CI supply-chain-verify job | Syft generates SBOMs for all services | CI workflow step output | CycloneDX SBOM artifacts | |
| 36 | +| 26 | Release provenance attestation | Release workflow (release.yml) | cosign attest with SLSA3 provenance | CI workflow attestation step | Signed provenance attestation | |
| 37 | + |
| 38 | +## End-to-End Enforcement Paths |
| 39 | + |
| 40 | +### Path 1: Bad Attestation → Service Startup Blocked |
| 41 | +``` |
| 42 | +Runtime Attestor detects TPM2 quote mismatch |
| 43 | + → State transitions to "failed" |
| 44 | + → POST to Incident Recorder: class=attestation_failure, severity=critical |
| 45 | + → Incident Recorder creates incident with auto-containment |
| 46 | + → Containment: freeze_agent + disable_airlock + force_vault_relock |
| 47 | + → Recovery: requires operator ack + re-attestation ceremony |
| 48 | +``` |
| 49 | +**Test:** `TestChain_AttestationFailure_ContainmentDispatched` |
| 50 | + |
| 51 | +### Path 2: Baseline Mismatch → Degraded → Incident → Containment |
| 52 | +``` |
| 53 | +Integrity Monitor detects file hash mismatch |
| 54 | + → State transitions to "degraded" |
| 55 | + → POST to Incident Recorder: class=integrity_violation, severity=high |
| 56 | + → Incident Recorder creates incident with auto-containment |
| 57 | + → Containment: freeze_agent + disable_airlock + force_vault_relock |
| 58 | + → State latched until manual review |
| 59 | +``` |
| 60 | +**Test:** `TestChain_IntegrityViolation_FreezeAndDisable` |
| 61 | + |
| 62 | +### Path 3: High-Risk Agent Action → Two-Phase Approval |
| 63 | +``` |
| 64 | +Agent planner proposes TRUST_CHANGE step |
| 65 | + → Policy engine evaluate_with_evidence: decision="ask" |
| 66 | + → Step remains PENDING until user approves via /v1/task/<id>/approve |
| 67 | + → On approval: token re-verified, step signature re-checked |
| 68 | + → Executor re-validates capability before execution |
| 69 | +``` |
| 70 | +**Test:** `test_two_phase_actions_require_approval` |
| 71 | + |
| 72 | +### Path 4: MCP Request with Tainted Input → Deny/Sanitize |
| 73 | +``` |
| 74 | +MCP Firewall receives request from tainted session |
| 75 | + → TaintState checked for session: external-data label found |
| 76 | + → TaintRule "no-external-to-write" matches target tool |
| 77 | + → Decision: deny with reason "taint rule violation" |
| 78 | + → Audit entry with taint evidence |
| 79 | +``` |
| 80 | +**Test:** `TestAdversarial_TaintBypassAttempt` |
| 81 | + |
| 82 | +## Operator Verification |
| 83 | + |
| 84 | +An operator can verify the enforcement chain is active by: |
| 85 | + |
| 86 | +1. **Check service health:** `curl http://localhost:8515/health` — incident recorder reports open incident count |
| 87 | +2. **Check recovery status:** `curl http://localhost:8515/api/v1/recovery/status` — pending recovery ceremonies |
| 88 | +3. **Export forensic bundle:** `curl http://localhost:8515/api/v1/forensic/export` — signed evidence package |
| 89 | +4. **Check attestation state:** `curl http://localhost:8505/api/v1/state` — current attestation status |
| 90 | +5. **Check integrity state:** `curl http://localhost:8510/api/v1/state` — current integrity baseline status |
| 91 | +6. **Verify audit chain:** `curl http://localhost:8496/v1/audit/verify` — MCP firewall audit chain integrity |
0 commit comments