This document explains what Fence protects, what it trusts, and what remains outside its security guarantees. It is intended for workflow authors, maintainers, and security reviewers.
Review this threat model before changing the supported runners, platform profile, launcher, privilege controls, evidence format, or public security claims. The v0 specification defines the full contract; the implementation history explains how Fence reached its current design.
Fence uses a schema-9 policy and schema-5 runtime evidence. The main branch contains source code only. Each published Action includes the reviewed wrapper, the exact agent binary, and a schema-4 manifest in a signed distribution commit. The wrapper rejects outdated evidence, stale verification, malformed wildcard records, missing workers, and agent processes that do not match the running systemd service. Changes to this contract must update the agent, wrapper, tests, and version together in one reviewed pull request.
Fence protects GitHub-hosted x64 jobs running ubuntu-24.04 or ubuntu-latest when it runs as the first workflow step. Releases test block and audit modes on both runner labels. Fence verifies the runner's security controls instead of requiring a fixed image fingerprint.
The main risks are how Fence starts its root-owned agent, translates DNS responses into firewall rules, removes sudo and container access, and verifies its post-job evidence. Fence limits outbound network access, but it cannot stop data from being sent to allowed GitHub services, user-approved destinations, or services sharing an allowed IP address.
In block mode, only root-owned host sockets can reach Azure WireServer at 168.63.129.16 on TCP ports 80 and 32526. Audit mode records other WireServer traffic without blocking it. Azure Instance Metadata Service at 169.254.169.254:80 remains available to host and forwarded traffic, including later workflow steps. Standard block mode depends on removing sudo and container access so untrusted steps cannot reach root-only services; audit mode and unsafe_preserve do not make the same containment claim.
Fence covers:
- The GitHub Action wrapper and bundled Linux agent in
action/. - Configuration, DNS mediation,
nftables, NFLOG, privilege lockdown, runtime storage, service supervision, and local attribution insrc/. - Hosted-runner checks in
.github/workflows/integration.ymland.github/workflows/action-acceptance.yml. - Release and bundle verification in
.github/workflows/release.yml,script/assemble-action-bundle, andscript/validate-action-bundle.
This threat model assumes:
- Fence runs before checkout, setup, or other untrusted workflow steps.
- The runner is an ephemeral GitHub-hosted x64 job using
ubuntu-24.04orubuntu-latestand meets Fence's runner security requirements. - The hosted image and privileged platform processes have not replaced a trusted executable before Fence captures it. Fence verifies executable identity after capture; it does not authenticate earlier file contents.
- Later workflow steps can run arbitrary commands as the unprivileged
runneruser and may have access to credentials or sensitive source code. - The Linux kernel, GitHub runner control plane, hosted image supply chain, and GitHub Actions service are trusted.
- Standard block mode uses
container_policy: disable;unsafe_preserveandauditprovide weaker isolation. - Fence has no remote control plane, telemetry upload, or runtime agent or policy download.
Fence does not protect against:
- A compromised kernel, hypervisor, or GitHub platform.
- Self-hosted or long-lived runners, ARM, Windows, macOS, or jobs running inside containers.
- Sensitive data sent through approved HTTPS or HTTP destinations.
- Data encoded in allowed wildcard DNS names.
- A malicious step intentionally causing its own job to fail.
- Missing process attribution or a lack of full process isolation.
Adding runner types, supporting job containers, or changing the default GitHub policy requires another threat-model review.
- Action launcher: Validates native inputs, creates root-owned launcher files, protects its runtime with a read-only mount, starts the service, and waits until the agent is ready (
action/main.cts,action/lib.cts). - Resident Rust agent: Checks the service and configuration, applies protections, supervises its workers, and verifies their state every five seconds (
src/cli.rs,src/lifecycle.rs,src/dns_mediator.rs). - Network controls: The
nftablesrules, DNS mediator, pinnedRunner.Worker, and NFLOG reader enforce and record the runner's network policy (src/nft.rs,src/nft_backend.rs,src/nflog.rs). - Privilege controls: Runner security checks, verified privileged executables, effective-access checks, sudo rollback, container shutdown, and root-process inventories prevent common privilege bypasses (
src/hosted_runner.rs,src/trusted_executable.rs,src/local_control.rs,src/lockdown.rs). - Local evidence: Root-owned readiness files, reports, worker health, and the protected post hook show whether protections remained active (
src/runtime.rs,src/findings.rs,action/post.cts). - Release verification: Pinned build inputs, signed distribution commits, acceptance tests, artifact attestations, checksums, and
action-release.jsonconnect reviewed source commitMto published Action commitD(.github/workflows/release.yml,script/assemble-action-bundle).
- Workflow author -> Action launcher: Native inputs or bounded raw JSON configure the Action. The wrapper rejects conflicting inputs; the agent rejects unknown fields and invalid values (
action/lib.cts,src/config.rs::parse_and_normalize). - Runner user -> root launcher: Fixed
sudoandsystemd-runcommands start one root-owned service. Configuration files are copied to fixed root-owned paths; arbitrary commands and executable paths are rejected (action/main.cts,src/lifecycle.rs). - Root agent -> Linux host controls: Verified executable descriptors and generated firewall rules can change only reviewed sudo, container, resolver, and
nftablessettings. The runner cannot write those trusted paths, and subprocess output and runtime are bounded (src/trusted_executable.rs,src/lockdown.rs,src/nft_backend.rs,src/dns_mediator.rs). - Workflow process -> DNS mediator: Fence binds its resolver read-only over either a root-owned regular
/etc/resolv.confor a reviewed systemd-resolved target. It verifies the mount the host actually sees; it does not trust the original file's nameservers. Only modes that keep Docker available set up its separate DNS route. Block mode forwards only approvedAandAAAAqueries; audit mode observes traffic without claiming containment (src/dns_mediator.rs). - DNS mediator -> fixed resolver and firewall owner: local UDP and TCP queries share the bounded root-only UDP resolver path. An approved answer is withheld until all matching transport rules are applied and structurally verified (
src/dns_mediator.rs::MaterializationSubmitter). - Platform compatibility -> GitHub service domains: Fence permits fixed workflow roots, five exact reviewed static results-storage compatibility accounts, and at most eight single-label
*.githubapp.comnames unless broad GitHub compatibility is disabled. Each resulting HTTPS grant is available to other local code and remains an explicit residual channel (src/platform_profile.rs,src/dns_mediator.rs). - User wildcard policy -> concrete DNS names: One- and two-label wildcard patterns share a limit of eight hostnames per job. Failed lookups still count because DNS names can carry data. CNAMEs must form one bounded chain rooted at the requested hostname, keep the original policy, and end in a matching address; responses without addresses grant no access (
src/hostname_policy.rs,src/dns_mediator.rs). - Pinned runner -> additional GitHub results storage: by default, Fence accepts up to four other exact results-storage names only when their host DNS sockets belong to the unique pinned
Runner.Workeridentity. The resulting HTTPS grants are also available to other local code (src/attribution.rs::TrustedRunnerWorker,src/dns_mediator.rs). - Explicit artifact compatibility -> additional GitHub results storage: block-only
allow_github_artifacts: truepermits a uniquely owned host DNS socket belonging to a runner-UID-matching, bounded descendant of the pinnedRunner.Workerto authorize an exact GitHub-shaped account within the same shared four-account lifetime budget. The distinctopt_in_github_artifact_dnsorigin and verified process ancestry do not authenticate an official action, GitHub's ownership of the account, a signed upload URL, or uploaded contents. Later workflow code can reuse the resulting TCP-443access to exfiltrate data (src/attribution.rs,src/dns_mediator.rs). - CNAME lineage -> restricted storage: exact and wildcard user hostnames cannot derive non-static GitHub results-storage accounts; every restricted account remains subject to the selected default or explicit opt-in attribution boundary and the shared four-account cap.
- Kernel NFLOG -> resident agent: Group
4242copies at most 64 packet bytes. Fence extracts approved endpoint metadata and discards the raw bytes (src/nflog.rs,src/findings.rs). - Finding -> attribution worker: A queue of up to 128 requests matches local sockets against bounded
/procsnapshots. Reports include only attribution status, actor class, PID, executable name, and up to four parent executable names (src/attribution.rs). - Resident agent -> post hook: The runner can read root-owned readiness and report files but cannot modify them. The post hook verifies the live service, worker health, fresh evidence, wildcard records, rejection counters, protected mounts, and runtime identity before trusting a report (
src/runtime.rs,action/post.cts). - Release workflow -> distribution commit: after all protected checks pass on source commit
M, the workflow builds the artifact once, assembles the bundle offline, and creates signed childDwith exactly the two generated bundle files. Full Action acceptance, block and audit checks on both runner labels, and asset attestations precede publication of the immutable tag andaction-release.json. Fence verifies those published assets and clears the temporary refs before adding the consumer pin to the release notes (.github/workflows/release.yml,script/assemble-action-bundle).
flowchart TD
W["Workflow and later steps"] --> A["Protected Action launcher"]
A --> S["Root resident agent"]
W --> D["Local DNS mediator"]
D --> S
D --> G["Approved GitHub endpoints"]
S --> K["Kernel and host controls"]
S --> E["Root-owned local evidence"]
E --> P["Protected post hook"]
| Asset | Why it matters | Security objective (C/I/A) |
|---|---|---|
| Workflow credentials and tokens | Later steps may receive credentials capable of repository or release changes. | C, I |
| Checked-out source and build outputs | Exfiltration or modification can compromise proprietary source or published artifacts. | C, I |
| Effective network policy | A missing or broader rule changes the core protection claim. | I, A |
| Sudo and container lockdown | Either path can restore root-equivalent authority and bypass network controls. | I |
| Trusted executable and local root-control identity | A replaced privileged command or additive root listener can invalidate the host-control claim. | I |
| Resident agent and protected Action runtime | Replacement can forge evidence, disable monitoring, or restore access. | I, A |
| Local readiness and report evidence | Operators and the post hook use it to decide whether the job remained protected. | I, A |
| Release agent and bundle provenance | A substituted binary compromises every adopting workflow. | I |
| Runner security controls | Unsafe changes to sudo, container, or privileged service access can invalidate lockdown assumptions. | I |
- Run arbitrary native code as the later workflow's
runneruser. - Read workflow-readable files, source, environment values, and credentials.
- Generate DNS and network traffic, including traffic to approved endpoints.
- Race local files and processes before readiness, or modify runner-writable paths after Fence starts.
- Generate large amounts of traffic within Fence's NFLOG, DNS, reporting, and attribution limits.
- Use sudo or Docker before Fence verifies that they are disabled, or use containers when
unsafe_preserveis explicitly enabled.
- Compromise the Linux kernel, GitHub service, or reviewed hosted-runner image.
- Gain undisclosed root access after Fence starts in standard block mode on a supported runner.
- Modify root-owned runtime files, the read-only Action mount, or the bundled binary after Fence starts without exploiting the kernel or another privileged component.
- Force Fence to inspect encrypted content sent to an approved destination.
| Surface | How reached | Trust boundary | Notes | Evidence (repo path / symbol) |
|---|---|---|---|---|
| Action native inputs | Workflow YAML | Author -> launcher | Bounded strings and multiline allowlist grammar; raw JSON is mutually exclusive. | action/lib.cts::defaultInlineConfig |
| Agent configuration | Root-owned config file | Launcher -> root agent | 256 KiB cap, strict schema, typed hostname/IP/CIDR and port validation. | src/config.rs::read_config_bounded, parse_and_normalize |
| Trusted service entry | fence run --config |
Root process -> protected lifecycle | Requires root, fixed config path, matching systemd unit and MainPID. | src/lifecycle.rs::validate_production_service_context |
| Local DNS UDP/TCP | Host and Docker resolver traffic | Workflow process -> root mediator | Direct host resolver mount, separate Docker routing, canonical bounded queries, fixed listeners, deadlines, policy classification. | src/dns_mediator.rs::start_dns_proxy |
| Results-storage DNS | Exact GitHub-shaped storage hostname | Pinned runner -> root mediator; optionally pinned-worker descendant -> root mediator | Default unique Runner.Worker identity; explicit artifact opt-in with unique runner-UID-matching socket ownership, revalidated bounded worker ancestry, distinct authorization provenance, strict grammar, one shared four-account cap, and HTTPS-only materialization. Account names do not authenticate GitHub ownership or upload contents. |
src/attribution.rs::TrustedRunnerWorker, src/platform_profile.rs::matches_results_storage_hostname, src/dns_mediator.rs::requires_runner_results_storage_provenance |
| NFLOG netlink socket | Owned kernel log group | Kernel -> agent | Fixed group/prefix, 64-byte copy bound, duplicate/trailing attribute rejection. | src/nflog.rs::extract_logged_prefix |
/proc attribution |
Internal finding tuple | Agent -> kernel process metadata | Fixed queue and scan caps; ambiguous ownership is not guessed. | src/attribution.rs::ProcAttributor |
nft subprocess |
Generated program and structured state | Agent -> kernel firewall | Fixed binary/args, bounded IO/time, JSON verification, singleton owned table. | src/nft_backend.rs::NativeNftBackend |
| Trusted executable set | Twelve fixed command paths | Agent -> privileged host execution | No-follow descriptor capture, exact metadata/device/inode revalidation, ACL-aware effective access, no raw-path fallback. | src/trusted_executable.rs::TrustedExecutableSet |
| Local root-control inventory | Bounded kernel TCP listener dumps and /proc Unix socket, owner and container state |
Agent -> host privilege state | Reviewed root-service identities, complete bounded observations, and a pinned post-setup resident baseline. The single reviewed UUID idle/active transition requires the original systemd owner, fixed socket, protected executable, exact service cgroup, and a non-root system UID; it cannot introduce an endpoint. | src/local_control.rs::observe_local_control_inventory |
| Sudo/container controls | Root-owned policy files, services, and sockets | Agent -> host privilege state | Complete sudo-policy pins, verified runner grant removal, safe Docker absence or shutdown, in-memory pre-ready rollback, and an irreversible post-ready commit. | src/lockdown.rs::SystemLockdownControl |
| Runtime evidence files | Root writes, runner reads | Agent -> post hook | No-follow fixed paths, exclusive readiness, atomic reports, owner/mode checks. | src/runtime.rs::ProductionRuntimeStore |
| Protected post hook | GitHub post-job invocation | Runner -> evidence validator | Writable self-bind guards on renameable ancestors, read-only mounted source, device/inode and digest records, live PID, and fresh report validation. | action/post.cts::main |
| Release and bundle publication | Merge-triggered release workflow and offline assembler | Source M -> distribution D -> consumer |
Pinned actions, protected-main-only environment, reviewed version merge as sole human authorization, signed one-parent exact-diff commit, complete acceptance/canary gates, checksums, source-bound attestations, immutable tag to D, and verified action-release.json. |
.github/workflows/release.yml, script/assemble-action-bundle |
- Send data to an allowed destination: A later step reads a token or source file and sends it to an approved GitHub service, allowlisted hostname, wildcard match, or shared IP address. Fence cannot inspect encrypted request contents.
- Regain root access: A later step uses a remaining sudo or container-control path to change
inet fence_v0and allow arbitrary traffic. Fence checks trusted paths, root-controlled services, and privilege removal before startup; later changes are reported as critical. - Expand access through DNS: A later step uses an allowed hostname, CNAME, or shared address to reach another service. Fence bounds hostnames, alias depth, TTLs, and transports, but cannot prove which TLS service owns an IP address.
- Connect before the firewall updates: A client tries to connect immediately after a DNS response. Fence withholds that response until the matching firewall rules are applied and verified; rejected updates return
SERVFAIL. - Replace the post hook: A later step changes the registered Action code or its parent directory to forge a successful result. Fence protects writable ancestors, mounts the runtime read-only, and verifies mount identity, file identity, and content digests.
- Forge or replay evidence: A later step writes a false report or reuses an old healthy report after killing the agent. Fence checks root ownership, the live service PID, worker health, a monotonic verification sequence, and the 20-second freshness limit.
- Change the firewall after startup: A later step or runner-image change removes an owned firewall rule. Checks run every five seconds and fail the job on critical drift, but traffic during that interval remains a known risk.
- Substitute a release binary: an attacker changes the bundled executable independently of reviewed source. The release workflow reuses one artifact built from
M, requiresDto be a signed one-parent child with an exact two-file diff, compares the committed bytes to the artifact, runs complete acceptance and canary gates onD, and verifies source-bound attestations. The immutable tag and full-SHA mapping are public during final verification; only after it succeeds and temporary refs are cleared does Fence advertise the consumer pin. Offline CI revalidates the schema-4manifest and binary digest. - Overload local reporting: A later step floods DNS, NFLOG, or process attribution. Fixed queue, scan, and report limits protect memory, but the step can still slow down or fail its own job.
- Reuse an authorized results account: after one of the five static compatibility accounts is prehydrated or the pinned runner authorizes an additional exact storage account, later workflow code connects to the same resolved HTTPS addresses. Fence cannot determine whether an encrypted request carries a GitHub-issued signed URL, another valid credential, or unrelated data.
| Threat ID | Threat source | Prerequisites | Threat action | Impact | Impacted assets | Existing controls (evidence) | Gaps | Recommended mitigations | Detection ideas | Likelihood | Impact severity | Priority |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| TM-001 | Malicious workflow process | Residual root-equivalent path, unreviewed root service, or unsafe runner change | Regain privilege and change firewall or agent state | Arbitrary egress and forged evidence | Credentials, policy, reports | Descriptor-pinned commands, ACL-aware path checks, bounded reviewed root services, pinned resident inventory, and verified sudo/container controls (src/hosted_runner.rs, src/trusted_executable.rs, src/local_control.rs, src/lockdown.rs) |
A compromised runner image, dynamic loader, shared library, or privileged platform process remains trusted | Require fail-closed security checks and destructive hosted tests on supported runner labels | Scheduled block/audit canary failure, setup rejection, or critical local-control finding | Low | High | High |
| TM-002 | Malicious workflow process | Access to an approved GitHub, exact user, or wildcard-derived destination | Exfiltrate sensitive data through allowed HTTPS or DNS behavior | Credential/source disclosure | Credentials, source | Exact profile roots, opt-out for broad platform roots, exact-depth wildcard grammar, shared eight-name lifetime cap, typed transports, and disclosed limits (src/hostname_policy.rs, README.md) |
Core GitHub reporting, wildcard query labels, CNAME delegation, and shared IPs remain channels | Keep wildcard use explicit, use least-privilege job tokens, and prefer exact names where practical | DNS/finding summary, wildcard admission/rejection evidence, and audit-mode tuning | High | High | High |
| TM-003 | Malicious workflow process or DNS response | Authorized exact name, wildcard match, CNAME, or address rotation | Expand usable addresses or race first connection | Policy broadening or unexpected denial | Effective policy, job availability | Canonical A/AAAA queries, response-local linear CNAME validation rooted at the echoed question, terminal address-owner checks, exact label-depth matching, shared name/depth/TTL caps, queried-root policy retention, and owner-coordinated atomic authorization plus verified materialization (src/dns_mediator.rs) |
IP authorization cannot prove TLS service identity; no public-suffix ownership validation is performed | Preserve response-local lineage, ordered owner-side revalidation, exact-depth matching, lifetime admission bounds, and complete apply-and-verify gating | DNS evidence counters, wildcard admissions, materialized allowances, and critical backend findings | Medium | High | High |
| TM-004 | Malicious workflow process | Writable launcher/post/binary, renameable registered-path ancestor, or evidence path | Replace validator or forge healthy evidence | False success after lost controls | Agent, post hook, reports | Root-owned copy, writable self-bind ancestor guards, read-only runtime bind mount, device/inode and digest records, no-follow files, live PID/freshness checks, schema-5 wildcard-evidence validation, and hosted tamper coverage (action/main.cts, action/post.cts, src/runtime.rs) |
Kernel or privileged mount bypass is out of scope; resident verification remains periodic | Keep exact path-guard/runtime manifests, worker set, freshness bounds, atomic schema adoption, and hosted tamper tests | Post-hook integrity or freshness failure | Low | High | Medium |
| TM-005 | Local process or host drift | Ability to alter owned kernel state after readiness | Remove or replace firewall rules | Temporary or persistent unintended egress | Network policy | Exact structured state verification every five seconds and terminal critical health (src/nft_backend.rs, src/dns_mediator.rs) |
Detection is periodic rather than instantaneous | Keep interval fixed and evaluate event-driven integrity only with bounded complexity | Critical drift finding; Action post failure | Medium | High | High |
| TM-006 | Workflow author or malicious config producer | Control of Action inputs before launcher validation | Inject paths, nft syntax, oversized policy, or ambiguous JSON | Privileged mutation or resource exhaustion | Host state, availability | Strict JSON, unknown-field rejection, fixed paths, typed entries, fixed limits (action/lib.cts, src/config.rs) |
Raw JSON remains an advanced surface | Preserve schema-1 strictness; add fields only through reviewed typed models |
Structured pre-mutation setup failure | Low | High | Medium |
| TM-007 | Supply-chain attacker | Ability to alter a release asset, workflow dependency, candidate commit, or release mapping | Distribute an agent not built by the reviewed workflow | Fleet-wide compromise | Release agent, downstream workflows | SHA-pinned actions, protected-main-only release environment, one reviewed source/version merge, exact one-parent signed D, exact two-file diff, complete acceptance/canary gates on D, checksums, non-draft immutable release tag targeting D, source-ref/source-commit/signer-digest-bound attestations, verified action-release.json, and offline bundle validation (.github/workflows/release.yml, script/validate-action-bundle) |
Attestation and commit signing trust GitHub identity and the reviewed workflow commit | Add SBOM and auditable/reproducible binary work as post-v0 hardening | Candidate verification, release verification, bundle validation, and mapped-SHA canary | Low | High | Medium |
| TM-008 | Malicious workflow process | Ability to generate local load | Saturate DNS, NFLOG, reports, or attribution scans | Job slowdown or failure | Job availability, evidence completeness | Queue/sample/query/scan/report caps and explicit truncation (src/dns_mediator.rs, src/attribution.rs, src/findings.rs) |
Fence does not guarantee availability against later code | Keep limits non-configurable in v0; review CPU cost with real workloads | Warning counters, truncation, critical worker health | High | Medium | Medium |
| TM-009 | Local process race or namespace boundary | Socket disappears, is shared, or is outside the scanned namespace | Produce missing or ambiguous process attribution | Reduced incident context, not control bypass | Local evidence | Unique-owner requirement, bounded statuses, no guessing (src/attribution.rs) |
Attribution is inherently best effort | Keep attribution advisory; do not gate containment on individual matches | not_found, ambiguous, and limit statuses |
High | Low | Low |
| TM-010 | Malicious workflow process | A static compatibility account, a runner-authorized account, or an explicitly opted-in artifact-storage account is reachable | Request or reuse a resolved HTTPS address, send sensitive artifact contents, or use a signed URL | Data exfiltration through an exact required or explicitly enabled GitHub-shaped storage channel | Credentials, source | Five source-defined exact compatibility accounts, pinned-worker-only dynamic authorization by default, explicitly selected and uniquely attributed pinned-worker-descendant artifact compatibility, revalidated bounded runner-UID-matching ancestry, distinct provenance, one shared four-account dynamic cap, bounded TTL, TCP 443, and explicit warning evidence (src/platform_profile.rs, src/attribution.rs, src/dns_mediator.rs) |
Fence cannot prove that a matching account belongs to GitHub, authenticate an official uploader, inspect TLS contents, restrict artifacts to intended files, or revoke signed URLs | Keep artifact compatibility disabled unless needed; preserve exact account grammar, runner-UID and descendant attribution, shared cap, existing CNAME restrictions, and distinct warning evidence | Authorized-account origins, opt-in status, artifact warning, and DNS counters | Medium | High | High |
- Critical: Standard block reports success while arbitrary egress or root access remains possible, a published binary differs from the reviewed artifact, or untrusted input gains root execution before startup.
- High: An attacker sends protected credentials through an unexpected default channel, permanently disables a protection, or forges post-job evidence.
- Medium: A bounded race temporarily changes policy, a malicious step can fail its own job, or exploitation also requires a privileged or platform compromise.
- Low: Process attribution is missing, low-sensitivity metadata is exposed, or a noisy failure is already blocked and clearly reported.
Severity depends on context. An approved GitHub destination can be a high-risk data channel in a job with credentials, while missing process attribution is low risk because attribution does not enforce policy. Kernel compromise would have critical impact but is outside this model.
| Path | Why it matters | Related Threat IDs |
|---|---|---|
action/main.cts |
Builds privileged launcher state, protects the runtime, and starts the root service. | TM-001, TM-004, TM-006 |
action/post.cts |
Converts local evidence and live service state into final job success or failure. | TM-004, TM-005 |
action/lib.cts |
Owns wrapper input parsing, path derivation, evidence validation, and summary sanitization. | TM-004, TM-006, TM-009 |
src/config.rs |
Defines the strict public policy parser and fixed input bounds. | TM-006 |
src/lifecycle.rs |
Enforces root/MainPID trusted-service identity and resident lifecycle rules. | TM-001, TM-004 |
src/runtime.rs |
Protects root-owned config, readiness, state, and report filesystem boundaries. | TM-004, TM-006 |
src/hostname_policy.rs |
Merges platform and user hostname transports into the logical policy. | TM-002, TM-003 |
src/dns_mediator.rs |
Implements DNS authorization, runner-bound results storage, refresh, materialization ordering, worker supervision, and reports. | TM-002, TM-003, TM-005, TM-008, TM-010 |
src/nft.rs |
Renders the deterministic owned firewall program and rule classes. | TM-001, TM-005 |
src/nft_backend.rs |
Applies and structurally verifies privileged kernel state through bounded subprocesses. | TM-001, TM-005 |
src/nflog.rs |
Parses the bounded kernel event wire format and rejects ambiguous attributes. | TM-008, TM-009 |
src/findings.rs |
Reduces packet prefixes to approved report metadata and keeps local tuples internal. | TM-008, TM-009 |
src/attribution.rs |
Scans bounded /proc state, pins Runner.Worker, attributes DNS sockets, and defines the local metadata privacy boundary. |
TM-008, TM-009, TM-010 |
src/trusted_executable.rs |
Captures and revalidates the fixed privileged executable set and descriptor-only execution boundary. | TM-001 |
src/local_control.rs |
Acquires and verifies the bounded root TCP/Unix and container-control inventory before readiness and during resident checks. | TM-001, TM-005, TM-008 |
src/lockdown.rs |
Enforces ACL-aware path invariants, removes and verifies sudo/container bypass paths, and owns pre-ready rollback state. | TM-001 |
.github/workflows/release.yml |
Connects reviewed source M to signed distribution D, validated release assets, and the immutable full-SHA consumer mapping. |
TM-007 |
.github/workflows/action-drift-canary.yml |
Resolves a verified release mapping or explicit full SHA and tests block and audit modes on both supported runner labels. | TM-001, TM-007 |
script/assemble-action-bundle |
Deterministically assembles the mode-0644 binary and schema-4 manifest from explicit local release inputs without network access. |
TM-007 |