security
SECURITY LLD
Tamper resistance, sandboxing, remote scan policy, and security deep dives.
Context Rail
Tags and Themes
On This Page
- 1. Document Purpose
- 2. Security Objectives
- 2.1 Primary Objectives
- 2.2 Non-Objectives
- 3. Threat Model
- 3.1 In Scope Adversary Capabilities
- 3.2 Out of Scope (Current Release)
- 4. Security Modes and Policy Semantics
- 4.3 Protection Profiles
- 4.1 Mode Resolution Rules
- 4.2 Tamper Response Policy
- 5. Component Architecture
- 5.1 Security-Critical Modules
- 6. Artifact Format and Cryptographic Construction
- 6.1 Signed Artifact Envelope (.mu)
- 6.1.1 Standalone Release Trailer
- 6.2 Encrypted Metadata Payload
- 6.3 Encryption Layers
- 7. Key Derivation and Password Handling
- 7.1 Password KDF (Argon2id)
- 7.2 Password Quality Policy
- 7.3 Build-Time Profile Binding
- 7.3 Deterministic Local Password Fallback
- 8. Signing and Trust Model
- 8.1 Signature Primitive
- 8.2 Verification Paths
- 8.3 Signing Key Injection
- 9. Runtime Security Gate (runner.Run)
- 9.1 Telemetry Export Hook
- 9.2 Standalone Trailer Validation
- 9.3 Process-Protection Probe Enforcement
- 9.4 Remote Process Scan Enforcement
- 10. VM Runtime Protection Internals
- 10.1 Offset-Aware Instruction Decode
- 10.2 Runtime Integrity Baselines
- 10.3 Probe Scheduler
- 10.4 Integrity Response
- 10.5 Builtin Capability Gating
- 11. In-Memory Object Protection
- 11.1 VM Stack/Object Paths
- 11.2 Secure Wrappers (object/secure_memory.go)
- 11.3 Stream Offset Convention for Object Types
- 12. Anti-Debug Design
- 12.1 Entry Point
- 12.2 Windows Signals
- 12.3 Linux Signals
- 12.4 Darwin Signals
- 12.5 Enforcement Staging
- 13. Telemetry and Audit
- 13.1 Counters
- 13.2 APIs
- 13.3 Audit Stream
- 14. runtime configuration setting Contract
- 14.1 Trust and Keys
- 14.2 Tamper Policy
- 14.3 Probe and Process-Scan Gates
- 14.4 Observability
- 15. Error and Failure Semantics
- 15.1 Canonical Security Errors
- 15.2 Policy-Dependent Behavior
- 15.3 Design Tradeoff
- 16. Detailed Dataflow
- 17. Testing and Verification Strategy
- 17.1 Unit/Integration Coverage Highlights
- 17.2 CI Security Profile
- 18. Security Invariants (Must Hold)
- 19. Residual Risks and Limitations
- 20. Operational Guidance
- 20.1 Recommended Production Baseline
- 20.2 Developer Baseline
- 21. Future Hardening Backlog (LLD-Level)
- 22. Appendix A: Key Functions by Responsibility
- Build-Time
- Run-Time Gate
- Runtime VM
- Security Core
- 23. Appendix B: Mode/Policy Decision Table
- 24. Appendix C: Design Review Checklist
1. Document Purpose
This document defines the low-level security design for Mutant's bytecode generation, signing, transport, loading, verification, runtime execution, anti-debugging, integrity monitoring, and telemetry paths.
It is implementation-accurate to the current codebase and intended for:
- Security engineering and code reviews
- Incident response and operations enablement
- Regression prevention for future security changes
- Test strategy and CI policy enforcement
This LLD focuses on anti-tamper and anti-piracy controls under an offline-first threat model.
Companion deep dives:
2. Security Objectives
2.1 Primary Objectives
- Ensure tampered artifacts are detected before or during execution.
- Ensure secure mode is fail-closed by default.
- Protect payload confidentiality and integrity at rest.
- Reduce effectiveness of dynamic analysis/debugging.
- Detect runtime instruction tampering and respond per policy.
- Provide observable security signals via telemetry and audit output.
2.2 Non-Objectives
- Absolute malware-grade anti-debug resistance (not possible in pure userland).
- Hardware-rooted trust chain (not implemented yet).
- Remote attestation and centralized key management (not implemented yet).
3. Threat Model
3.1 In Scope Adversary Capabilities
- Reads and modifies
.muartifacts on disk. - Attempts re-signing with attacker-generated keypairs.
- Runs runtime under debugger/instrumentation.
- Patches bytecode/in-memory instruction regions.
- Replays older artifacts or malformed payloads.
- Manipulates runtime configuration settings at launch.
3.2 Out of Scope (Current Release)
- Kernel-level adversaries with arbitrary memory write.
- Hypervisor-level introspection attacks.
- Physical attacks against hardware secrets.
4. Security Modes and Policy Semantics
Mutant currently has three practical launch postures:
- Secure mode (
--secure, default):
- Runtime posture defaults to secure execution gates.
- Trusted signer pinning is enforced only when
--signer-authis enabled. - Default tamper response is
terminate. - If trusted key env is not set, runtime bootstraps a local persistent keypair and uses the local public key as trusted key for signer-auth verification.
- Compatibility mode (
--compat):
- Signature verification uses embedded signer key (format validity only).
- Default tamper response is
warn.
- Developer mode (
--dev):
- Runtime behavior is forced to compatibility mode.
- If no runtime password is supplied for
.mu, default deterministic local password fallback is used (mutil.GetPwd()). - Intended for local testing convenience, not production hardening.
4.3 Protection Profiles
Mutant also supports a protection profile layer via runtime setting.
Supported values:
minimal
- Favors compatibility and operator convenience.
- Defaults tamper policy to
warn. - Defaults risky builtin groups to allow-all unless an explicit capability list is set.
standard
- Default profile when the runtime setting is unset or invalid.
- Keeps secure mode fail-closed and compatibility mode warn-by-default.
paranoid
- Favors maximum tamper resistance.
- Defaults tamper policy to
terminatewhen this profile is selected. - Explicit
runtime settingstill has higher precedence.
Profile precedence:
- Explicit
runtime settingstill wins when set. - Explicit
runtime settingstill wins when set. - Profile selection only controls defaults.
4.1 Mode Resolution Rules
CLI precedence is "last matching mode flag wins" due to linear arg scanning.
- Encounter
--compator--dev-> mode becomes compatibility. - Encounter
--securelater -> mode becomes secure again.
4.2 Tamper Response Policy
Policy source: env variable runtime setting.
Valid values:
warn: log and continuedelay: sleep then continueterminate: return error/fail
Defaults:
- secure mode:
terminate - compatibility/dev mode:
warn
Delay tuning:
runtime settingin[0..5000]- fallback default:
250ms
5. Component Architecture
5.1 Security-Critical Modules
security/crypto.go
- AES-GCM payload encryption/decryption
- metadata serialization/parsing
security/kdf.go
- Argon2id derivation and parameter validation
- deterministic HKDF utilities
security/signing.go+security/signatures.go
- Ed25519 signatures
- signed artifact envelope parse/verify
- trusted key pinning
security/secure_random.go
- ChaCha20 offset-aware stream masking
- secure compare/zeroing helpers
security/response_policy.go
- central tamper response decisions
security/telemetry.go
- counters, JSON snapshot/export, audit log
security/antidebug_*.go
- platform-specific debugger detection
runner/runner.go
- execution gate and staged enforcement
vm/vm.go
- runtime decode path + integrity probes + policy integration
code/code.go
- offset-aware operand reads
object/secure_memory.go
- secure wrappers and object offset conventions
6. Artifact Format and Cryptographic Construction
6.1 Signed Artifact Envelope (`.mu`)
Outer format:
HEADER |-| ENCODED_DATA |-| SIGNATURE_HEX |-| PUBLIC_KEY_HEX |-| FOOTER
Constants:
HEADER = MUTFOOTER = ANTOUTER_SEPERATOR = |-|
Notes:
- Parser validates minimum parts and header/footer sentinels.
- Signature/public key are hex encoded.
ENCODED_DATAis the serialized encryption metadata string.
6.1.1 Standalone Release Trailer
Release binaries produced by the generator append a standalone trailer after the embedded runtime payload.
Current format version: V3
MUTANTBC | version | payload_len | payload_sha256 | canary | profile_code | provenance_sha256
Field details:
version
- V1 and V2 are accepted for legacy compatibility.
- V3 is the current emission format.
payload_len
- Big-endian
uint64payload length.
payload_sha256
- SHA-256 over the embedded bytecode payload.
canary
- Short SHA-256 derived guard used to detect trailer corruption.
profile_code
- Encoded protection profile selected at build time.
1 = minimal,2 = standard,3 = paranoid.
provenance_sha256
- SHA-256 over
payload || payload_sha256 || profile_code. - Used to detect tampering and mismatched release provenance.
Compatibility rules:
- Runner validates V3 first, then V2, then V1.
- V1 and V2 remain supported for older artifacts.
- V3 is required for new release builds.
6.2 Encrypted Metadata Payload
ENCODED_DATA format in password mode:
ciphertext_b64 | salt_hex | <empty-sourcehash> | true | iter | memory | threads
Deterministic mode variant stores sourceHash and false.
Constants:
- inner separator:
SEPERATOR = | - AEAD associated data:
ENCSIG = MUTANT
6.3 Encryption Layers
Compilation encryption layering (current implementation):
- VM bytecode and constants are stream-masked (
mutil.EncryptByteCode,SecureXOR). - Full gob byte slice is XOR-wrapped with embedded random key
(
SecureXOREncrypt). - Result is AES-GCM encrypted using Argon2id-derived key (
AESEncrypt). - Encrypted metadata is signed with Ed25519 (
SignCode).
Rationale:
- AES-GCM gives confidentiality + integrity for payload.
- Signature protects authenticity and allows trusted signer pinning in secure mode.
- Additional stream/XOR layers increase analysis friction.
The standalone release trailer adds a separate provenance check path so the runtime can validate the generated build profile and trailer integrity before payload decode.
7. Key Derivation and Password Handling
7.1 Password KDF (Argon2id)
Derivation path:
DeriveKeyFromPassword(password, salt)- defaults:
- time: 1
- memory: 64 MB (
64*1024KB) - threads: 4
- key length: 32 bytes
Validation hard bounds:
- time:
[1..8] - memory:
[64MB..4GB]in KB units - threads:
[1..16]
7.2 Password Quality Policy
Easy memorable passwords
7.3 Build-Time Profile Binding
Release generation binds the selected protection profile into the standalone
trailer via the profile_code field.
Security implication:
- The build mode becomes auditable in the emitted artifact.
- Trailer provenance mismatch is treated as tamper.
- Runtime behavior still honors explicit environment overrides for policy controls.
7.3 Deterministic Local Password Fallback
mutil.GetPwd() uses HKDF-SHA512 over fixed context constants to produce a
deterministic local key string.
Used when:
- Single-arg
.mut/.muconvenience paths. --devmode running.muwithout explicit-pwd.
Security implication:
- deterministic and recoverable from binary/source; convenience only.
- not a production secret.
8. Signing and Trust Model
8.1 Signature Primitive
- Algorithm: Ed25519
- Signing input: SHA-256 hash of
ENCODED_DATA
8.2 Verification Paths
- Compatibility verification (
VerifyCode):
- Parses embedded public key and signature.
- Verifies signature correctness for envelope integrity.
- Does not enforce signer identity trust.
- Secure verification (
VerifyCodeWithTrustedPublicKey):
- Parses embedded public key/signature.
- Loads trusted key from env
runtime settingwhen set. - Falls back to local key bootstrap resolution when env is absent.
- Constant-time compares embedded key with trusted key.
- On mismatch returns
ErrUntrustedSigner. - Verifies signature using trusted key.
8.3 Signing Key Injection
Build/signing key source:
runtime settingpreferred for stable signer identity.- If absent, local persistent keypair is loaded or bootstrapped from local keystore.
Operational risk:
- unmanaged local bootstrap keys can diverge from official release trust anchors if not governed by deployment policy.
9. Runtime Security Gate (`runner.Run`)
9.1 Telemetry Export Hook
If runtime setting is set, runner defers telemetry JSON export
at function exit.
9.2 Standalone Trailer Validation
Before signature verification and decode, runner performs standalone trailer validation when the binary appears to carry an appended payload.
Validation order:
- V3 trailer
- V2 trailer
- V1 trailer
Checks performed:
- trailer marker and version
- payload length bounds
- payload SHA-256
- canary (V2+)
- profile code validity and provenance hash (V3)
Failure handling:
- checksum mismatch -> reject payload
- canary mismatch -> reject payload
- provenance mismatch -> reject payload
- unsupported trailer version -> reject payload
9.3 Process-Protection Probe Enforcement
At both pre-decode and pre-execution stages, runner evaluates process
protection probes (process_injection, trampoline, iat_got,
module_integrity, memory_page_anomaly) when
runtime setting=1.
Rollout gate:
runtime settingcontrols whether runner executes process-protection enforcement.- default is enabled when unset.
- disable values:
0,false,off,no.
Enforcement threshold:
- Any signal with
detected=trueandconfidence >= 80is treated as a process protection event.
Response path:
- Telemetry event:
process_protection_detected - Policy dispatch:
ApplyTamperResponse(process_protection_detected, ...) - Default result: terminate in secure mode, warn in compatibility/dev mode.
9.4 Remote Process Scan Enforcement
Runner executes RunRemoteProcessScan at both pre-decode and pre-execution
stages.
Gates and modes:
runtime setting=1enables scan execution.runtime setting=off|observe|enforcecontrols decision behavior.- Scanner errors are telemetry-visible and non-blocking.
Current enforcement behavior:
observe: records telemetry only, never blocks execution.enforce: blocks only when a verdict reaches the configured critical score.- High-risk but non-critical verdicts remain advisory.
Current implementation status:
- Configuration, correlator, telemetry, and runner policy integration are implemented.
ScanRemoteProcessesWindowscurrently returns no verdicts (safe no-op), so remote verdict generation is scaffolding-ready but not yet signal-rich.
10. VM Runtime Protection Internals
10.1 Offset-Aware Instruction Decode
VM fetch path decrypts opcode/operands at exact stream offsets:
- opcode:
SecureXOROneAt(ins[ip], seed=inslen, password, offset=ip) uint16operands:ReadUint16(..., offset=ip+1)uint8operands:ReadUint8(..., offset=ip+1)
Security effect:
- avoids fixed-position-independent keystream reuse.
- ties decrypt stream byte to logical position.
10.2 Runtime Integrity Baselines
- Each compiled function instruction slice gets SHA-256 baseline at registration.
- Main function baseline seeded at VM init.
- Additional function baselines registered when frames are pushed.
10.3 Probe Scheduler
runIntegrityProbes() triggers checks by schedule:
- periodic: every
integrityEverysteps (default 64) - jittered: when
stepCount % 97 == integrityJitter % 97 - sweep: every 251 steps checks all active frames
10.4 Integrity Response
If current instruction hash differs from expected baseline:
RecordIntegrityFailure(stage)ApplyTamperResponse(integrity_failed, stage, secureMode=true, err)
Important implementation detail:
- VM currently calls tamper response with
secureMode=truefor integrity failures, making secure defaults (terminate) apply unless env override downgrades policy.
10.5 Builtin Capability Gating
Risky builtins are gated by explicit capability names and default policy from the selected protection profile.
Current capability groups:
command_execfilesystemnetwork
Behavior:
minimalprofile defaults to allow-all.standardandparanoidprofiles default-deny the risky groups.- Explicit
runtime settingoverrides the profile default.
11. In-Memory Object Protection
11.1 VM Stack/Object Paths
push()attempts to encrypt objects before storing.pop()attempts to decrypt encrypted objects before use.- arrays/hashes decrypt elements during construction.
- builtin call arguments decrypted before invocation.
11.2 Secure Wrappers (`object/secure_memory.go`)
Available primitives:
SecureGlobal
- encrypted value storage, typed set/get, secure clear.
SecureStack
- optional auto-encrypt idle entries after timeout.
SecureConstantPool
- encrypted constants with cache.
Current wiring note:
- VM runtime protection path primarily uses
mutil.EncryptObjectandmutil.DecryptObjectin stack/global/constant handling. object/secure_memory.goprovides additional wrappers and utilities that can be used by integrations, but they are not the primary VM storage path today.
Current policy gate:
runtime setting=runtime|wrapper- default is
runtimefor performance-safe operation wrapperenables optional global wrapper usage where object types are supported
Current helper-scope decision:
- no additional secure-memory helper types are required for this release beyond
SecureGlobal,SecureStack, andSecureConstantPool - revisit helper expansion only if threat-model requirements exceed current runtime encryption + optional wrapper mode coverage
11.3 Stream Offset Convention for Object Types
objectStreamOffset:
- integer -> 64
- string -> 128
- boolean -> 192
- default -> 256
Purpose:
- deterministic per-type stream segmentation and reduced overlap.
Limitations:
- plaintext exists transiently during runtime operations and conversions.
- Go string immutability limits guaranteed in-place wipe.
12. Anti-Debug Design
12.1 Entry Point
IsDebuggerPresent() dispatches by OS:
- windows ->
isDebuggerPresentWindows - linux ->
isDebuggerPresentLinux - darwin ->
isDebuggerPresentDarwin
12.2 Windows Signals
High-confidence (single hit triggers):
IsDebuggerPresentCheckRemoteDebuggerPresentNtQueryInformationProcess(ProcessDebugPort)NtQueryInformationProcess(ProcessDebugObjectHandle)
Low-confidence weak hits (threshold-based):
OutputDebugStringtiming anomaly- common debugger DLL presence
Decision rule:
shouldTriggerDebuggerByWeight(highConfidence, weakHits, weakThreshold=2)
12.3 Linux Signals
/proc/self/statusTracerPid != 0- parent commandline pattern matching for debugger/re tools
- debugger-related env markers (
GDB_*,LLDB_*,VALGRIND_*,LD_PRELOAD, etc.)
12.4 Darwin Signals
sysctlP_TRACED flag- parent process pattern match
- debugging env markers (
LLDB_*,DYLD_INSERT_LIBRARIES, etc.)
12.5 Enforcement Staging
Runner checks anti-debug at:
pre-decodepre-execution
On detection:
- telemetry increment
- policy application (
warn/delay/terminate)
13. Telemetry and Audit
13.1 Counters
Atomic counters:
debugger_detectedintegrity_failedsignature_failedsandbox_detectedprocess_protection_detectedanti_tamper_probe_invokedanti_tamper_probe_errorremote_process_scan_invokedremote_process_scan_errorremote_process_suspiciousremote_process_criticalcommand_attemptcommand_blockedcommand_succeededcommand_failed
13.2 APIs
SecurityTelemetrySnapshot()-> mapSecurityTelemetryJSON()-> serialized JSONExportSecurityTelemetry(path)-> file write mode0600ResetSecurityTelemetry()-> test/ops reset
13.3 Audit Stream
If runtime setting=1, writes stderr event lines:
[security-audit] ts=<unix> event=<...> stage=<...>
14. runtime configuration setting Contract
14.1 Trust and Keys
runtime setting
- required in secure runtime mode
- trusted signer pinning key (ed25519 public key, hex)
runtime setting
- optional generator signing private key
- stable artifact signer identity when set
runtime setting
- optional override for local key bootstrap directory
- defaults to
<home>/.mutant/keys
14.2 Tamper Policy
runtime setting=warn|delay|terminateruntime setting= integer ms in[0..5000]
14.3 Probe and Process-Scan Gates
runtime setting=1enables anti-tamper probe execution.runtime settinggates runner enforcement of the focused 5-probe process-protection set.runtime setting=1enables remote process scan manager.runtime setting=off|observe|enforce.runtime setting= positive integer, default32.runtime setting= positive integer, default1000.runtime setting= comma-separated process names.
14.4 Observability
runtime setting=1to enable stderr audit linesruntime setting= output path for telemetry JSON
15. Error and Failure Semantics
15.1 Canonical Security Errors
ErrWrongSignatureErrPasswordRequiredErrInvalidMetadataErrDebuggerDetectedErrSandboxDetectedErrProcessProtectionDetectedErrUntrustedSigner
15.2 Policy-Dependent Behavior
Same event can either:
- terminate with original error (
terminate) - continue with warning (
warn) - continue after delay (
delay)
15.3 Design Tradeoff
- Secure defaults maximize resistance but may impact debuggability.
- Compatibility/dev improves operator ergonomics but weakens security guarantees.
16. Detailed Dataflow
17. Testing and Verification Strategy
17.1 Unit/Integration Coverage Highlights
security/security_test.go
- trusted key pinning success/failure
- argon2 bounds validation
- stream XOR offset correctness
- telemetry counters/json/export
- policy defaults and response behavior
- compatibility mixed artifact behavior
- anti-debug weighting logic
- anti-tamper probe routing and process-protection signal set
runner/runner_test.go
- secure mode malformed/tampered payload rejection
- compatibility mode continue-on-signature-failure behavior
- secure-mode termination on high-confidence process-protection signal
- advisory behavior for sub-threshold process-protection signal
vm/vm_security_policy_test.go
- integrity tamper behavior under
warn,delay,terminate
17.2 CI Security Profile
Workflow .github/workflows/security-profile.yml:
- strict env defaults (
terminate, delay=0, audit=1) - targeted security packages + VM policy test
- optional telemetry artifact upload
18. Security Invariants (Must Hold)
- When
--signer-authis enabled in secure mode, trusted signer verification must be enforced (trusted env key or local bootstrap trusted key). - In signer-auth path, signature mismatch/untrusted signer must fail unless policy is explicitly downgraded by env.
- Integrity mismatch must always record telemetry before policy action.
- Metadata parser must reject malformed Argon2 parameters.
- Opcode/operand decode must stay offset-aware.
- Telemetry export path must not fail open to panic.
19. Residual Risks and Limitations
- Compatibility/dev mode can be misused in production if not controlled.
- Env-driven policy downgrades (
warn/delay) can reduce enforcement. - Userland anti-debug remains bypassable by binary patching.
- No hardware trust anchor or attestation.
- Deterministic fallback password is convenience-only and not secret.
- Full Windows runtime integration tests on real CI runners remain pending.
- Full compile-sign-run-tamper rerun lifecycle tests remain incomplete.
20. Operational Guidance
20.1 Recommended Production Baseline
- Launch with
--secureonly. - Set
runtime settingto release signer key. - Set
runtime setting=terminate. - Set
runtime setting=0unless delay strategy is intentional. - Enable telemetry export and audit in monitored environments.
20.2 Developer Baseline
- Use
--devfor local test convenience only. - Avoid using
--devartifacts/behavior as production acceptance signal. - Keep test environment policy explicit to avoid accidental drift.
21. Future Hardening Backlog (LLD-Level)
- Add compile-sign-run-tamper-rerun end-to-end suites.
- Add real Windows runner-based anti-debug integration tests.
- Add signer key rotation and multi-key trust set support.
- Add self-integrity hashing of selected runtime text/function regions.
- Add policy lock mode to ignore environment downgrades in production builds.
- Consider hardware-backed key protection for signing workflows.
- Expand telemetry schema with per-event reason codes and monotonic sequence IDs.
22. Appendix A: Key Functions by Responsibility
Build-Time
generator.Generategenerator.encryptCodesecurity.AESEncryptsecurity.SignCode
Run-Time Gate
runner.Runrunner.enforceAntiDebugrunner.decryptCode
Runtime VM
vm.Runvm.runIntegrityProbesvm.verifyFrameIntegrity
Security Core
security.VerifyCodesecurity.VerifyCodeWithTrustedPublicKeysecurity.ApplyTamperResponsesecurity.Record*telemetry APIssecurity.IsDebuggerPresent
23. Appendix B: Mode/Policy Decision Table
| Execution Posture | Signature Verification Path | Default Policy | Wrong Signature / Untrusted Key | Debugger Hit | Integrity Mismatch |
|---|---|---|---|---|---|
Secure (--secure) |
Trusted key pinning required | terminate | stop by default (unless env downgrade) | stop by default (unless env downgrade) | stop by default (unless env downgrade) |
Compatibility (--compat) |
Embedded key verification | warn | continue/log by default | continue/log by default | continue/log by default |
Developer (--dev) |
Compatibility path forced | warn | continue/log by default | continue/log by default | continue/log by default |
24. Appendix C: Design Review Checklist
- Any new security check records telemetry before response.
- Any new response path uses
ApplyTamperResponseconsistently. - Any new opcode/operand decode remains offset-aware.
- Any metadata schema changes preserve strict parse/validation behavior.
- Any new compatibility shortcut is explicitly blocked in secure mode.
- Any CI changes preserve targeted security profile execution.
End of document.