20 lines
4.3 KiB
Markdown
20 lines
4.3 KiB
Markdown
# Static safety audit
|
|
|
|
Status: pass for final review; execution remains approval-gated.
|
|
|
|
- **Endpoint:** daemon service, daemon configuration, client context, environment, and tests name only `unix:///run/user/1200/docker.sock`. No TCP, SSH, rootful, fallback, or inherited default endpoint is accepted.
|
|
- **Lifecycle:** no linger artifact or command exists. Root explicitly controls `user@1200.service`; the namespace unit cannot start until a separate operator approval marker exists.
|
|
- **Filesystem:** the complete user manager receives a private read-only `/srv` with only `/srv/le-app-codex` rebound, empty private `/var`, `/mnt`, `/media`, and `/opt`, private `/tmp`, protected homes/processes, explicit production/archive/transitional path tests, and inaccessible rootful sockets/runtime data.
|
|
- **Devices/resources:** closed device policy permits only FUSE and TUN. Aggregate CPU, memory, swap, and task limits cover the user manager and descendants. Hard disk-growth enforcement is deferred and is not a Phase 2B installation blocker; these mandatory controls are not a storage quota.
|
|
- **IPv4-only:** the namespace receives only `10.200.120.2/30`; namespace-scoped IPv6 is disabled; daemon IPv6/ip6tables are disabled; nftables drops IPv6 from the project interface.
|
|
- **Egress:** only DNS to `9.9.9.9`/`149.112.112.112` and public TCP 80/443 are accepted. Nonpublic/reserved IPv4, loopback, link-local/metadata, multicast, all RFC1918 Docker/LAN/WireGuard ranges, direct SMTP, and all other protocols/ports drop.
|
|
- **Host isolation:** host-to-project forwarding and unsolicited inbound traffic drop. Project traffic to host private addresses and observed public/NAT address `74.67.173.56` drops. RootlessKit host-loopback and external port publication are disabled and tested negatively.
|
|
- **DNS:** the operator-approved Quad9 malware-blocking, DNSSEC-validating IPv4 pair avoids any LAN exception. `/etc/resolv.conf` is rebound read-only for the user manager. The observed `192.168.10.1` router resolver remains denied.
|
|
- **Existing nftables:** the verified ruleset has no `le_app_codex` objects. Dedicated tables avoid editing Docker-owned chains. Interface-scoped terminal drops remain effective alongside existing Docker base chains.
|
|
- **Inventory:** the root record checksums pass. UID 1200 is inactive, not lingering, has no process/runtime/socket; project ACLs and modes match Phase 1; no project-rooted mounts exist; all 41 Docker networks fall within denied IPv4/IPv6 space.
|
|
- **Rollback:** names and paths are Phase 2B-specific; teardown deletes only the project tables, namespace/veth, marker, and manifest-listed files.
|
|
- **Stage 1 installer:** installs exactly 16 allowlisted files; long Docker-context paths are single-line variables; existing shared parents are accepted only when real, root-owned, and not group/other writable; existing shared parent metadata is never changed.
|
|
- **Stage 1 state/rollback:** immutable mode `0600` manifest/checksum generations record commit, artifact-manifest digest, hashes, pending/completed files, pending/created/pre-existing directories, time, and host. A verified regular `current` pointer is switched by one atomic rename only after the new generation is synced and semantically validated. Rollback accepts `IN_PROGRESS` subsets or an exact 16-file `COMPLETE`, atomically tombstones the transaction before removal, re-verifies remaining objects on retry, and calls `rmdir` only for allowlisted recorded directories.
|
|
- **Crash recovery:** deterministic `.phase2b-new` payload temporaries are covered by `FILE_PENDING`; hidden incomplete state generations never become authoritative; old generations are retained. The parser shared by installer, rollback, and `tests/32-stage1-state-tests.sh` rejects blank, duplicate, unknown, malformed, unapproved, or escaping records. The state resolver separately rejects symlinked or escaping pointers/generations and unverified generation content. Publication failpoints cover initial and updated `IN_PROGRESS`, final `COMPLETE`, and both sides of the atomic pointer switch.
|
|
|
|
Hard stops remain: changed Docker version/launcher hash, changed inventory, public/NAT address drift, missing approval marker at namespace-start time, pre-existing project tables/namespace, any acceptance failure, or any endpoint other than the single rootless Unix socket. `ProtectProc=invisible` remains an unproven runtime acceptance candidate.
|