Binary Artifact Security Deep Dive
The flag carries a path, never key material. Key material in an environment variable is invisible in the command an analyst records and is inherited by every child process; a path is safe to write…
1. Scope#
This deep dive covers binary artifact security for Mutant from generation to runtime load:
- Signed
.muenvelope format and trust model. - Standalone trailer V1/V2/V3 validation and provenance checks.
- Runtime mode and signer-auth behavior at load time.
- Failure paths and telemetry hooks.
Primary implementation anchors:
security/signatures.gosecurity/signing.gosecurity/key_bootstrap.gogenerator/writebinary.gorunner/runner.go
2. Signed Envelope Security#
Mutant signed payload format:
MUT |-| ENCODED_DATA |-| SIGNATURE_HEX |-| PUBLIC_KEY_HEX |-| ANT
Verification paths:
VerifyCode
- Validates envelope structure and Ed25519 signature with embedded key.
- Used in compatibility mode.
VerifyCodeWithTrustedPublicKey
- Validates envelope and signature.
- Requires trusted key pinning material.
- Rejects if embedded key does not match trusted key (
ErrUntrustedSigner).
3. Signer Trust Resolution#
Trusted key resolution order when signer-auth path is used
(ResolveTrustedPublicKeyHexFromPath, security/key_bootstrap.go):
- If
--trusted-key <path>was given, read the hex-encoded public key from that file. A malformed, wrong-sized or missing file is a hard failure: there is no silent fallback to the keystore, because verifying against a key the operator did not name is worse than refusing to run. - Otherwise bootstrap/load the local keypair in the keystore and trust the local public key.
The flag carries a path, never key material. Key material in an environment variable is invisible in the command an analyst records and is inherited by every child process; a path is safe to write into case notes. See CONFIGURATION_POLICY.md.
Key files:
ed25519_private_key.hexed25519_public_key.hex
Key dir:
<home>/.mutant/keys, fixed. <home> is the home directory the account
database records for the user running Mutant (the token's profile directory on
Windows, /etc/passwd on Linux, the directory service on macOS), never HOME
or USERPROFILE; an account the database does not list is refused.
SetLocalKeyStoreDirForTesting redirects it for tests only.
4. Runtime Signature Decision Matrix#
The runner behavior is controlled by two switches:
secureMode(derived from CLI mode flags)enforceSignerAuth(derived from--signer-auth/--no-signer-auth)
Behavior:
secureMode=true,enforceSignerAuth=true
- Runs trusted-key signature verification.
- Signature errors go through tamper policy.
secureMode=true,enforceSignerAuth=false
- Skips signature verification path.
- Continues to anti-debug/sandbox/process protection and decode path.
secureMode=false
- Runs compatibility signature verification path.
- Signature failures are policy-driven (
warn|delay|terminate).
5. Standalone Trailer Attestation#
Release binaries append a trailer after payload:
V3 format:
MUTANTBC | version | payload_len | payload_sha256 | canary | profile_code | provenance_sha256
Validation order in runner:
- Try V3 trailer.
- Fall back to V2.
- Fall back to V1.
Validation checks:
- Marker and version.
- Payload length bounds.
- Payload checksum.
- Canary (V2+).
- Profile code validity and provenance hash (V3).
Tamper outcomes:
- Mismatch returns explicit trailer error (checksum/canary/provenance/version).
- Runner rejects payload extraction on trailer validation failure.
6. Profile Binding and Provenance#
Generation path binds runtime profile code into trailer:
generator/writebinary.gocallsResolveProtectionProfileCode.- Profile code is embedded as one byte.
- Provenance hash derives from payload + payload hash + profile code.
Security value:
- Build profile is auditable from artifact.
- Payload replay or profile mismatch changes provenance digest.
7. Policy and Telemetry Coupling#
When signature verification runs and fails:
RecordSignatureFailure(stage)increments telemetry.ApplyTamperResponse(...)executes warn/delay/terminate policy.
Telemetry export:
- In-process only.
SecurityTelemetrySnapshot()andSecurityTelemetryJSON()read the counters;ExportSecurityTelemetry(path)writes them to a file, but nothing in the runner calls it. - There is no audit stream:
auditEventis a no-op.
8. Operational Pitfalls#
- Secure mode does not imply signer-auth unless
--signer-authis supplied. - Compatibility mode can continue past signature failures under warn.
- Local key bootstrap is convenient, but a bootstrapped key trusts whatever
signed the artifact on this machine. Pass
--trusted-keyto pin a real signer. --compatand--devdowngrade the tamper response to a warning. This is the only way to soften it, it is visible in the command line, and it cannot be done behind an operator's back.
9. Recommended Production Posture#
- Use
--secure --signer-auth. - Pass
--trusted-key <path>naming the approved release signer's public key. - Do not pass
--compator--dev: secure mode already terminates on a tamper event, and that is the only way to getterminate. - Record the full command line alongside the artifact. It is the complete description of how the run was configured -- nothing is read from the environment. See CONFIGURATION_POLICY.md.