Security LLD Traceability Matrix

This document provides end-to-end traceability from security design intent to concrete implementation and validation.

1. Purpose#

This document provides end-to-end traceability from security design intent to concrete implementation and validation.

It maps:

  1. Security requirements and controls
  2. Implementation anchors (functions/files)
  3. Runtime configuration surfaces (flags/env)
  4. Test coverage and how it is enforced
  5. Residual gaps and next validation actions

2. Traceability Model#

Flowchart

Evidence levels used in this matrix:

  • I = implemented
  • T = tested
  • C = wired into the repository-wide go test ./... gate
  • P = partial / pending depth
  • D = declined by decision: no control exists, none is planned, and the decision is recorded beside the row

3. Security Control Matrix#

ID Control Requirement LLD Area Implementation Anchors Config Surface Tests / CI Evidence Status
SEC-001 Signed artifact envelope must be parsed and verified before execution Artifact format + trust model security/signatures.go, security/signatures.go, security/signatures.go, runner/runner.go Mode-driven path: --secure / --compat / --dev security/security_test.go, runner/runner_test.go I/T/C
SEC-002 Secure mode must pin signer identity to trusted key Secure mode semantics runner/runner.go, security/signatures.go, security/const.go --trusted-key <path> security/security_test.go, runner/runner_test.go I/T/C
SEC-003 Signature failure handling must be policy-driven Tamper response policy runner/runner.go, runner/runner.go, security/response_policy.go --secure / --compat / --dev security/security_test.go, runner/runner_test.go I/T/C
SEC-004 Payload confidentiality and integrity at rest must use AEAD Crypto layer security/crypto.go, security/crypto.go, security/const.go Password input and metadata indirect via runner decode path tests runner/runner_test.go I/T/P
SEC-005 Password-based key derivation must use bounded Argon2id params KDF hardening security/kdf.go, security/kdf.go, security/crypto.go password mode + metadata fields security/security_test.go I/T
SEC-006 Password quality policy required when explicit password mode is used Password policy security/kdf.go, generator/generate.go prompt / --password-file / --password-stdin (-password refused) covered by generator path behavior and policy validation unit scope I/P
SEC-007 Runtime instruction decode must be offset-aware to reduce keystream reuse VM decode hardening vm/vm.go, code/code.go, code/code.go, security/secure_random.go runtime password/seed context security/security_test.go, security/security_test.go I/T/C
SEC-008 Runtime integrity checks must detect instruction tampering VM integrity probes vm/vm.go, vm/vm.go, vm/vm.go policy + secure default behavior vm/vm_security_policy_test.go I/T/C
SEC-009 Integrity failures must trigger telemetry and policy action Telemetry + policy coupling vm/vm.go, security/telemetry.go, security/response_policy.go None; VM forces secure policy vm/vm_security_policy_test.go, vm/vm_security_policy_test.go, vm/vm_security_policy_test.go I/T/C
SEC-010 Anti-debug checks must be staged before decode and before execution Runtime gate enforcement runner/runner.go, runner/runner.go, runner/runner.go mode + tamper response env policy behavior tests security/security_test.go I/T/P
SEC-011 Debugger detection must be platform-specific with weighted signal logic on Windows Anti-debug platform design security/antidebug.go, security/antidebug_windows.go, security/antidebug_weighting.go, security/antidebug_linux.go, security/antidebug_darwin.go runtime OS selection security/security_test.go I/T/P
SEC-012 Security telemetry must support atomic counters and secure export Telemetry subsystem security/telemetry.go, security/telemetry.go, security/telemetry.go None; in-process API only security/security_test.go, security/security_test.go I/T/C
SEC-013 CLI must clearly resolve secure/compat/dev mode and developer fallback semantics CLI posture controls main.go, main.go, main.go, main.go --secure, --compat, --dev, --password-* operationally validated in local runtime use; no dedicated CLI parsing tests yet I/P
SEC-014 Generator must use a stable per-host signing identity Signing workflow generator/generate.go, generator/generate.go, security/key_bootstrap.go None; local keystore only indirectly validated by signature verification tests I/P
SEC-015 The security suites must run on every supported OS before a release Release validation CONTRIBUTING.md, SECURITY_LLD.md None; go test ./... with CGO_ENABLED=0 the suites themselves; nothing automates the "every OS" half since the CI workflow was removed I/P
SEC-016 Protection profile must define default tamper behavior Runtime policy profile security/profile.go, security/response_policy.go None; fixed at standard security/security_test.go I/T
SEC-017 Per-builtin capability configuration -- declined; none exists (note 1) Builtin capability gates None. A gate would have to cover: builtin/builtin.go, builtin/command_exec.go, builtin/fs.go, builtin/net.go, builtin/http.go None. No per-builtin gate exists (note 1) security/command_exec_bounds_test.go covers the fixed limits that do apply, there being no gate to test D
SEC-018 Standalone release artifacts must carry profile attestation and provenance Release trailer attestation generator/writebinary.go, runner/runner.go, security/profile.go, security/const.go build profile + release generation path runner/runner_test.go I/T

3.1 Note 1 -- SEC-017, per-builtin capability configuration#

There is no per-builtin capability gate, and none is planned for 2.6.0. This is a decision taken on 2026-10-10, not an unfinished item: a Mutant program carries the authority of the process that runs it, the same way a program written in Python, Ruby, Node or Go does. None of those puts a per-call gate in front of subprocess, os/exec or opening a socket either.

What follows from that, stated plainly because a reader deciding whether to run a program they did not write needs it stated rather than softened:

  • A program that can reach exec_string, exec_argv or cmd_run can run commands, and one that can reach the fs_*, net_* or http_* families can read files and open sockets, with this process's own permissions.
  • The operator's decision is whether to run the program, not what it may do once running. The controls that support that decision are the signed artifact envelope and the mode flags (SEC-001), not a capability set.
  • What does constrain command execution is fixed and not configurable: a 3-second timeout bounding the whole call rather than one process, 8 KiB kept of each output stream, a kill that reaches the process tree, and a shell named rather than written out as a command line. Those are limits on blast radius, not permissions, and they are tested in security/command_exec_bounds_test.go.
  • The LSP's commandInjection rule is an editor-time warning. It can be switched off and it does not run at execution time, so it is not an enforcement point.
  • The policy_* builtins are not this control under another name. They wrap Open Policy Agent, so a program loads a Rego module and asks it a question, and the program itself decides what to do with the answer. Nothing outside those five builtins calls the engine, so it is never consulted before a builtin runs.

The design is revisited if a user asks for it. Until then this row exists so that a reviewer auditing control coverage finds a recorded decision rather than a gap, and so that nothing in this repository describes the control as pending.


4. Runtime Decision Trace#

Sequence diagram

5. Flag Traceability#

Every switch is a command-line flag. Mutant reads no environment variable for configuration, so this section is the complete control surface. See CONFIGURATION_POLICY.md, which also lists the variables the Go runtime and Mutant's libraries still read on its behalf.

  1. Mode-flag validation
  • validateModeFlags rejects a command line naming two contradictory postures before any other work, so the selectors below are read from a command line that names at most one mode
  • anchor: main.go
  1. --secure / -secure
  • default secure posture selector and explicit assertion of it
  • anchor: main.go
  1. --compat / -compat
  • compatibility posture selector
  • anchor: main.go
  1. --dev / -dev
  • compatibility posture + default local password fallback for .mu when password omitted
  • anchors: main.go, main.go
  1. Password sources: prompt (default), --password-file, --password-stdin, --password-insecure; -password / -pwd / --password= / --pwd= are parsed only so the resolver can refuse them by name (since 2.6.0)
  • collected into a credential.Request by extractPasswordRequest, then resolved by credential.Resolver, which rejects a command line naming more than one source
  • the deprecated argv forms emit a warning naming the process-table exposure
  • anchors: main.go, credential/credential.go
  1. --signer-auth / --no-signer-auth
  • upgrade signature verification to a trusted public key, or decline to; self-verification is the floor in every mode either way
  • anchors: main.go, runner/runner.go
  1. --trusted-key <path>
  1. --security-log-level <level> / --log-level <level>
  • security logging verbosity in dev mode
  • anchor: main.go
  1. --timing
  • per-stage run timing on stderr
  • anchor: main.go

5.2 Fixed behaviour (no control surface)#

These were once environment variables and are now constants, with one entry that was never a control at all. Listed so a reviewer does not go looking for a control that used to exist, or never did:

  1. Protection profile -- standard (security/profile.go).
  2. Tamper response -- derived from the mode flags above (security/response_policy.go).
  3. Tamper delay -- 250 ms; no mode selects the delay response.
  4. Anti-tamper probe gate -- always on (security/antitamper_probe.go).
  5. Process-protection gate -- always on (runner/runner.go).
  6. Remote process scan -- off; test-only setter (security/processscan_config.go).
  7. Audit stream and telemetry export -- no-op and uncalled respectively (security/telemetry.go).
  8. Signing key -- local keystore only (security/key_bootstrap.go).
  9. Builtin capability configuration -- never existed and is not planned; declined 2026-10-10. See note 1 under the control matrix.

6. Test Coverage Map by Attack Scenario#

Attack Scenario Expected Security Behavior Primary Tests
malformed .mu envelope in secure mode reject before decode runner/runner_test.go
malformed envelope in compat mode policy may continue; fail later during decode runner/runner_test.go
tampered signer identity secure mode rejects untrusted signer runner/runner_test.go, security/security_test.go
trusted signer valid but payload unusable signature path passes, decode fails correctly runner/runner_test.go
integrity tamper under warn/delay/terminate policy-specific continue/fail behavior with telemetry increment vm/vm_security_policy_test.go
response policy default/override correctness secure default terminate, compat default warn, env override honored security/security_test.go, security/security_test.go
stream-mask roundtrip and offset byte correctness decryptability and offset-specific correctness security/security_test.go, security/security_test.go
telemetry JSON/export correctness counters and file export valid security/security_test.go, security/security_test.go
windows weak/high-confidence weighting threshold behavior stable security/security_test.go

7. Known Traceability Gaps#

The following areas are represented in LLD but only partially evidenced at integration depth:

  1. Real Windows runner integration execution with genuine debugger signals (P depth remains).
  2. Full compile -> sign -> run -> tamper -> rerun lifecycle integration suite.
  3. Dedicated CLI flag parsing tests for secure/compat/dev precedence.
  4. Explicit unit coverage for generator password complexity rejection path.
  5. Signed-key rotation lifecycle tests (multi-key trust/rollover not yet implemented).

  1. Add main CLI parsing tests covering mixed mode flag order and dev fallback behavior.
  2. Add e2e fixture tests that produce real .mu artifacts and validate tamper outcomes in all policies.
  3. Verify runtime anti-debug policy on a clean Windows host before each release. This was a CI job in the backlog; with no CI it is a release step, and it is manual.
  4. Done: negative tests for a malformed, wrong-sized and missing --trusted-key file (security/key_bootstrap_test.go).
  5. Add deterministic artifact compatibility tests to guard accidental secure/compat behavior drift.

9. Quick Audit Checklist (Reviewer Use)#

  1. Secure mode with --signer-auth resolves a trusted key, and a --trusted-key file that is missing or malformed fails the run rather than falling back.
  2. Any signature, debugger, or integrity event routes through policy layer.
  3. Telemetry increments occur before policy returns error on terminate.
  4. VM operand/opcode decode remains offset-aware.
  5. go test ./... has been run for this change — it includes the security suites and the configuration guard in policy/. Nothing runs it for you; say in the PR which OS you ran it on.
  6. Dev mode remains explicit and does not silently alter secure mode defaults unless chosen.

10. Probe and Process-Protection Traceability#

10.1 Control Additions#

  1. Master anti-tamper probe gate: antiTamperProbeEnabled, a compile-time true. Not configurable.
  2. Runner process-protection gate: isProcessProtectionEnabled(), which returns true. Not configurable.
  3. Runner enforcement threshold: any probe signal with detected=true and confidence >= 80. This is the only decision point left.

10.2 Implementation Anchors#

  1. Probe gate and engine: security/antitamper_probe.go
  2. Probe routing: security/antitamper_routing.go
  3. Probe implementations:
    • security/antitamper_detectors.go
    • security/antitamper_windows.go
  4. Runner enforcement path: runner/runner.go
  5. Builtin diagnostics probe use: builtin/security_status.go

10.3 Operational Notes#

  1. Runner enforcement probe scope is intentionally narrower than builtin diagnostic scope.
  2. If the master probe gate is disabled, runner process-protection enforcement will not execute probe logic even when the process-protection gate is enabled. Only a test can reach that state.

11. 2026-07 Code Sync Addendum#

This addendum captures code-accurate deltas that must be read together with the matrix above.

11.1 Signer-Auth Runtime Semantics#

Current implementation:

  1. Secure mode selection and signer-auth are independent runtime switches.
  2. Trusted signer verification path runs only when --signer-auth is present.
  3. --no-signer-auth keeps secure-mode runtime gates but skips signature verification path in runner.

Anchors:

  1. main.go
  2. runner/runner.go
  3. runner/runner_test.go

11.2 Remote Process Scan Control Surface#

Current implementation:

  1. Remote scan manager is gated by remoteScanConfigState.Enabled, which is false in every shipped binary and writable only by SetRemoteScanConfigForTesting.
  2. Mode is remoteScanConfigState.Mode (off|observe|enforce, default observe).
  3. Runner blocks only on enforce-mode critical verdicts.
  4. Scan errors are non-blocking and telemetry-visible.

Anchors:

  1. security/processscan_config.go
  2. security/processscan_manager.go
  3. runner/runner.go
  4. runner/runner_test.go

11.3 Remote Scan Runtime Depth#

Current implementation status:

  1. Types/config/correlator/manager/telemetry and runner integration are implemented.
  2. Windows scanner implementation currently returns empty verdicts (nil, nil), so enforcement path is wired but detector depth is still scaffolding-first.

Anchors:

  1. security/processscan_windows.go
  2. security/processscan_manager_test.go

End of document.

Related reading