System Security &
Authority Model
01 // THE CENTRAL PRINCIPLE
// released: capability check, service, audit · V0.11 branch (unreleased): every step, for two actions
agent intent → policy engine
→ risk/permission evaluation
→ user approval (where required)
→ deterministic privileged service
→ kernel operation → verification
→ audit → rollback/recovery
IN DEVELOPMENT
Intelligence / authority separation
DETERMINISTIC SYSTEM SIDE
- + policy & permission evaluation
- + approval at the console only
- + narrow privileged services
- + verification, audit, rollback
02 // TRUST BOUNDARIES
- BOUNDARY_01 CURRENT
Firmware/bootloader boundary
- BOUNDARY_02 CURRENT
Kernel trusted boundary
- BOUNDARY_03 CURRENT
Userspace boundary
- BOUNDARY_04 CURRENT
Privileged system-service boundary
- BOUNDARY_05 CURRENT
Untrusted application boundary
- BOUNDARY_06 UNRELEASED
AI/agent boundary
- BOUNDARY_07 CURRENT
External network boundary
03 // IN FORCE NOW
- CAPABILITY HANDLES
- DEFAULT DENY
- SANDBOXED FILESYSTEM
- SIGNED PACKAGES
- CPU-ENFORCED SEPARATION
- AUDIT TRAIL
- CONSOLE-ONLY AGENT AUTHORITY
- VERIFIED ACTIONS
- ESCAPED PROCESS OUTPUT
- VM CONTAINMENT
- UNSAFE MINIMIZED
04 // THREAT MODEL
| Risk | Vector | Mitigation |
|---|---|---|
| Host damage from OS testing | misconfigured VM (disk passthrough, raw device writes) | QEMU launches only project-generated images; no passthrough flags anywhere in scripts/harness; physical-hardware boot is out of scope |
| Kernel bug corrupting its own state silently | logic errors, bad unsafe | panic-on-invariant-violation; boot-stage markers; selftests; unsafe inventory |
| Malformed boot data | firmware/bootloader handoff anomalies | validate memory map/pointers before use; reject overlapping regions |
| Malformed initramfs | corrupt/hostile archive bytes | strict bounds-checked parsing with negative-case tests (planned with FS-001) |
| Supply-chain drift | dependencies with unexpected code | small pinned dependency set, Cargo.lock committed, rationale per kernel dependency |
| Secret leakage | tokens in commits/logs/CI | secret scan before pushes; env-var/platform secret stores only |
| Fake completion | claims without evidence | requirement matrix + machine-readable QEMU evidence; website generated from status/current.json; the build fails when the kernel version, status metadata or requirement states disagree |
| Hostile network input | malformed, spoofed or unsolicited frames | allocation-free parsers that refuse VLAN tags, fragments, bad checksums and every truncation; bounded ARP cache and socket queues; five hostile frames draw zero replies (verified). Since v0.9.0 the image answers TCP as well as ARP-for-us and ICMP echo, and neighbour discovery and ICMPv6 echo once IPv6 is brought up; v0.8.1 answers only ARP-for-us and ICMP echo |
| Hostile TCP peer | forged resets or SYNs, segments for no connection, connection-table exhaustion | Since v0.9.0 — v0.8.1 has no TCP. Every segment is checksummed against the pseudo-header of the addresses it arrived between and its options are length-checked; a RST is accepted only at exactly the expected sequence number, and a SYN or in-window RST elsewhere draws a challenge ACK (RFC 5961); a segment for no connection gets a RST, never to broadcast; 8 connections with fixed buffers. Not yet: keyed initial sequence numbers (RFC 6528) or rate-limited challenge ACKs |
| Tampered or foreign package | modified payload, unsigned or stranger-signed package, forged signature | SHA-256 integrity, then Ed25519 authenticity: corrupt, unsigned, stranger-signed and forged packages are each refused for their own reason (verified). Since v0.9.0 only an offline root is compiled in, and a signing key is trusted only through a root-signed certificate limited to a package-name scope and a release-epoch window — revoked, expired, out-of-scope and uncertified signers are each refused. v0.8.1 checks the signature against one compiled-in development key whose seed is published, so it proves the mechanism but anchors no trust |
| Stolen or misused signing key | a published development key (v0.8.1); any signing key can leak | Since v0.9.0 a leaked signing key is bounded by its certificate’s scope and validity window and retired by a root-signed revocation list, and within a boot, applying an older list than the current one is refused (host-tested); the published test key is certified only for hello-* fixture packages. Not covered: a stolen root key (it is kept offline for that reason), or an attacker who can rewrite the unauthenticated boot image. In v0.8.1 this is not mitigated — accepted for a pre-alpha build, and stated |
| Edited audit trail | records altered, deleted, reordered or inserted on disk; the whole trail rewritten | hash-chained records verified on every boot and reported TAMPERED. A whole-trail rewrite (in the limit, a valid empty trail) still passes the chain. Since v0.9.0 the saved head can be anchored with a witness off the disk, and a check reports MISMATCH when the trail recovered at boot disagrees — an explicit command, and the witness must be reachable. v0.8.1 cannot detect a whole-trail rewrite. Found after v0.10.0, true of every release since v0.8.0 and fixed on the V0.11 branch: the verifier cries wolf — a trail saved by any boot after the first, or after the in-memory ring dropped a record, or after audit verify, reads as TAMPERED although untouched (AUDIT11-001); and a crafted multi-megabyte trail on the disk panics boot recovery every time, an offline attacker’s denial of service (AUDIT11-003). On the V0.11 branch a tampered trail also stays reported across saves until the operator removes it |
| A program rewriting the evidence | fs_write or fs_delete on the audit trail or on a package’s .pkg/.ok files; a file name or file contents with a line break and a kernel marker in them | Not mitigated in v0.10.0 and earlier, found after v0.10.0 and fixed on the V0.11 branch: a program holding fs_write without a sandbox can replace the audit trail (in the limit with a valid empty one, which only the anchor catches) or delete a commit marker, rolling an application back (SEC11-001); and the kernel echoes names and contents a program chose unescaped, so a line break in a name prints a line that reads as a kernel marker (AUDIT11-002). The fix makes the trail and the package store kernel-owned, refuses names with control characters, and escapes every echo |
| Kernel touching user memory by accident | confused-deputy bugs, user pointers | SMAP forbids kernel access to user pages outside three declared windows; SMEP and UMIP on; W^X for user segments; a guard page below the user stack. Since v0.9.0 a zero-length copy never touches the user pointer: before that fix, found by the V0.10 work and confirmed on the V0.9 kernel, any program could panic the kernel with cap_list(NULL, 0) (SEC09-001, regression-checked in the gate). Since v0.10.0 a buffer the kernel writes must also be writable by the program at every level of the page walk: in v0.9.0 and earlier the kernel checked only that it was mapped, so any program could panic the kernel by pointing cap_list at its own read-only code or data (SEC10-001, found after v0.9.0) |
| Kernel stack overflow | a deep or oversized kernel call path — V0.9’s first TCP run overflowed the then-unguarded syscall stack into the capability table | Since v0.9.0 — not in v0.8.1: the stack every interrupt and exception from Ring 3 runs on (RSP0) and the double-fault stack sit on unmapped guard pages (both verified unmapped at boot); an RSP0 overflow ends in a double fault that names the stack instead of silent corruption, verified by a deliberate overflow in QEMU. Since v0.10.0 the syscall stack — the one V0.9’s TCP bug overflowed, unguarded in v0.9.0 — and every kernel task stack sit on guard pages too, each verified by a deliberate overflow |
| A misled or malicious agent | a spoofed inference service answering over unauthenticated IPC; a forged model or view digest; a stale view; a diagnosis the model does not support; an action that does not apply; proposal flooding | Shipped in v1.0.0 — released images before it have no agent. Everything the agent hands the kernel is a claim: the kernel refuses an unknown model, a view it never served that process or served more than 5 s earlier, a condition its own recomputation with the shipped model does not give, an action the fixed condition → action table does not allow or that does not apply to the system now, a malformed field, and a second pending proposal from the same submitter (8 slots); each refusal is named and audited, and nothing a proposal says acts until the console approves it. Not covered: IPC has no sender identity, so a malicious IPC holder can mislead a diagnosis — though not get an unjustified proposal filed |
| An approved action that fails or no longer fits | the system changed between proposal and approval; an action that does not take effect or makes things worse | V0.11, shipped in v1.0.0: approve refuses a proposal that is no longer pending and re-checks the precondition from fresh kernel facts (precondition_changed); each action is verified against a post-condition and rolled back if it fails — a control in which the executor does nothing shows the verification failing and the rollback running. The retry-service rollback kills only a live instance of that service under /sbin/init — found by the V0.11 review: the kernel had killed whatever pid init named, and a compromised init naming another service’s pid is now refused (not_an_instance). Not covered: verification checks one post-condition over a short window, not the system’s health afterwards, and init still names which instance of the service to stop. Only two actions exist, and proposals are held in memory only — they do not survive a reboot |
| A program redrawing what the operator approves | escape sequences, carriage returns and C1 controls in a program’s output moving the cursor over a kernel line such as a proposal preview | V0.11, shipped in v1.0.0: process output shows every control character except line feed and tab escaped, and the invisible Unicode characters that reorder or hide text as well — a right-to-left override could make reversed text display as a kernel marker (OUT11-001, host-tested, and a QEMU probe whose cursor-up, erase-line, carriage return and override arrive as text). Found after v0.10.0 by the V0.11 adversarial review, and true of v0.10.0: a program can print the kernel marker prefix after all, split across the kernel’s 256-byte output chunks or across two writes once every line buffer is taken (OUT11-002); and ps prints the path string a program passed to spawn, so a line break and a marker in a component that .. later removes print as a kernel line of their own (SEC11-002). Both are fixed on the V0.11 branch. Not covered: printable lookalike characters, and a line that merely looks like a preview, without the kernel prefix |
Explicitly out of scope today
05 // CAPABILITY MODEL
VERIFIEDsubject → capability → object → permitted operation → constraints → provenance