Logs the full output of the 9-agent deep-dive run on 2026-05-05 to
docs/research/2026-05-05-agent-wave/. Pulls every actionable finding
into one indexed location so v0.5.32 planning has a paper trail.
Files:
docs/research/2026-05-05-agent-wave/README.md — index
docs/research/2026-05-05-agent-wave/01-...real-hardware.md — Plymouth + LUKS edge cases
docs/research/2026-05-05-agent-wave/02-...firstboot-ux.md — SDDM + first-boot UX
docs/research/2026-05-05-agent-wave/03-...spike-plan.md — bootc-image-builder 1-week spike
docs/research/2026-05-05-agent-wave/04-...tier-2.md — AppArmor + nftables + audit + homed
docs/research/2026-05-05-agent-wave/05-...launch.md — threat model + v0.7 launch checklist
docs/research/2026-05-05-agent-wave/06-...log-capture.md — virtio-9p host-share for anaconda logs
docs/research/2026-05-05-agent-wave/07-...skel-branding.md — /etc/skel gap audit
docs/research/2026-05-05-agent-wave/08-...ci-hardening.md — SHA-pin actions + SBOM + SLSA L3
docs/research/2026-05-05-agent-wave/09-...failure-modes.md — real-hardware pessimistic audit
Plus the prior linter-applied:
docs/ROADMAP.md — Lessons learned section, v0.5.32 active block,
v0.6 promotion of veilor-postinstall + veilor-doctor,
v0.7 bootc spike scheduled
docs/THREAT-MODEL.md — drafted by Agent 5; in/out scope, comparison
matrix, v0.7 launch checklist
Top blockers identified for v0.5.32 (cross-cited in README):
1. Suspend/resume wifi death (kernel.modules_disabled=1)
2. veilor-firstboot.service WantedBy=graphical.target
3. kernel-upgrade grub drift
4. USBGuard hash-rules problem (already learned on onyx)
5. firewalld blocks tailscale0
6. /etc/skel/ empty
7. virtio-9p log capture replaces broken virtio-serial path
Wave + verifier pattern (per ROADMAP lessons learned #4) validated:
9 parallel agents on distinct topics produced converging blocker
list. The same pattern landed v0.5.31 four-bug fix from the prior
4-agent verification wave on v0.5.30 outcome.
152 lines
9 KiB
Markdown
152 lines
9 KiB
Markdown
# Threat Model
|
||
|
||
> **Status:** Draft for v0.7 public flex. Honest scope.
|
||
|
||
veilor-os is a hardened daily-driver desktop. Not a paranoia OS, not an
|
||
anonymity OS, not an isolation OS. This document exists so that
|
||
security-conscious developers, journalists, and activists can decide whether
|
||
the threat model fits their actual adversary before they trust the system.
|
||
|
||
If your adversary is on the "out of scope" list below, **use a different
|
||
tool**. veilor-os will not save you, and we will not pretend otherwise.
|
||
|
||
---
|
||
|
||
## In scope — what veilor-os defends against
|
||
|
||
| Adversary / scenario | veilor-os mitigation |
|
||
|---|---|
|
||
| Lost or stolen laptop, powered off | LUKS2 (aes-xts-plain64, argon2id, mem=1 GB) on root + swap-as-zram. Disk yields ciphertext. |
|
||
| Generic browser / email malware (drive-by RCE, malicious attachment) | SELinux enforcing + `veilor-systemd` policy + sysctl hardening (kptr_restrict, ptrace=2, perf=3, BPF JIT harden, full ASLR, no SUID core dumps). AppArmor stack lands in v0.5. |
|
||
| Console-side USB attack (BadUSB, rubber ducky, juice-jack) | USBGuard daemon, default-block, empty allowlist on first boot. New device = explicit operator allow. |
|
||
| SSH brute-force / credential-stuffing | sshd password-auth off, root login off, MaxAuthTries=3, fail2ban with sshd + pam-generic jails wired to firewalld rich-rule. |
|
||
| Post-incident forensics ("what happened?") | auditd rules covering passwd/shadow/sudoers/ssh/cron/sysctl/kernel modules and all privileged binaries. Logs survive reboot. |
|
||
| Supply-chain on the OS image itself | Fedora's signed shim → GRUB → kernel chain (Secure Boot enforced). v0.4 adds GPG-signed ISO + sha256 + own MOK. |
|
||
| Unprivileged local user attempting LPE | root account locked (`passwd -S root` → `L`), single sudo user with pwquality minlen=14 / 4 classes, kernel module loading frozen 30 s after graphical boot. |
|
||
| Network-listening services as attack surface | firewalld default zone = `drop`; only sshd answers. abrt/cups/avahi/bluetooth/ModemManager/kdeconnectd/PackageKit are masked. |
|
||
| Time-based MITM (back-dated certs, replay) | NTS-authenticated chrony, DNS-over-TLS via systemd-resolved, LLMNR off. |
|
||
|
||
---
|
||
|
||
## Out of scope — what veilor-os does NOT defend against
|
||
|
||
We are honest about this list because pretending otherwise is how people get
|
||
hurt. **If your adversary is here, pick a different tool.**
|
||
|
||
| Adversary / scenario | Why veilor-os doesn't help | Use instead |
|
||
|---|---|---|
|
||
| Nation-state firmware-level implant (UEFI, ME, BMC) | Secure Boot validates the OS, not the firmware below it. We do not flash custom firmware. | Heads / coreboot on supported hardware. |
|
||
| Evil-maid attack on a running, unlocked system | LUKS keys live in RAM while the system is up. A physically present attacker can dump RAM (cold boot, DMA via Thunderbolt, debug header). | Power off when unattended. Disable Thunderbolt DMA in firmware. Qubes-in-a-Faraday-bag if you're that target. |
|
||
| Hardware keylogger / hardware mod between keyboard and machine | We're software. Software cannot detect a passive hardware tap. | Physical custody of the device. Tamper-evident seals. |
|
||
| Targeted RCE on the user session (browser 0-day, signal-app exploit) | KDE Plasma is not sandboxed. A logged-in compromise has the user's full data and tokens. SELinux confines daemons, not the desktop. | Qubes (per-app VM isolation). |
|
||
| Side-channel attacks on AES (timing, cache, power analysis) | We use stock kernel crypto. No constant-time guarantees beyond what the kernel/CPU provide. | Threat-specific HSM. |
|
||
| Physical attack on a TPM2 chip (probe, glitch, decap) | We don't ship TPM2 binding yet. Even when v1.0 lands, TPM2 is not anti-tamper hardware. | Off-device key custody. |
|
||
| Network-level traffic correlation / traffic analysis | All packets leave the box on the local IP. We don't onion-route. | Tails, Whonix, Tor. |
|
||
| Trust-on-first-use attacks (user clicks "accept bad cert") | We can't override the user's decisions. Bad SSL/SSH key acceptance by the operator is out of scope. | Enrolment policy, MDM. |
|
||
| Adversary with sustained physical access and time | Given enough physical time and tools, any laptop falls. | Operational security, not OS choice. |
|
||
|
||
---
|
||
|
||
## Hardening tradeoffs (what you give up)
|
||
|
||
Hardening that breaks ordinary work gets called out, not hidden.
|
||
|
||
- **SELinux enforcing** — some apps (proprietary, out-of-tree) ship
|
||
without policy. Symptom: `EACCES` despite correct file perms.
|
||
Workaround: write a local policy module; do not switch to permissive.
|
||
- **LUKS2 argon2id (mem=1 GB / time=9)** — boot 5–30 s slower on older
|
||
CPUs. The cost of a passphrase that survives a GPU attacker.
|
||
- **USBGuard default-block** — every new device needs an explicit allow.
|
||
First-boot: plug trusted devices in, run `usbguard generate-policy`.
|
||
Forget this and your USB-C dock looks broken.
|
||
- **Module lockdown 30 s after graphical boot** — out-of-tree drivers
|
||
(NVIDIA proprietary, VirtualBox, out-of-tree wireguard) will fail.
|
||
Load early via initramfs or use the in-tree alternative.
|
||
- **firewalld zone = drop** — KDE Connect, mDNS printer discovery, SMB
|
||
browsing don't work until explicitly opened. This is the point.
|
||
- **No PackageKit / no Flatpak by default** — updates happen on your
|
||
terms via `dnf upgrade`.
|
||
|
||
---
|
||
|
||
## Where veilor-os IS like Tails / Whonix / Qubes
|
||
|
||
- Threat model published. Transparency about scope is the price of being
|
||
taken seriously.
|
||
- Default-deny firewall (`drop` zone, ssh inbound only).
|
||
- Encrypted at rest by default — LUKS2 + argon2id, no-disk-swap (zram).
|
||
|
||
## Where veilor-os DIFFERS
|
||
|
||
- **Daily-driver target.** Boot it once, install it, use it for years.
|
||
Not a session-only / amnesia OS.
|
||
- **Single-VM / single-kernel.** No per-app compartmentalisation. A
|
||
browser RCE owns your session. (See "out of scope".)
|
||
- **Persistent identity by design.** Your `~`, your keys, your shell
|
||
history persist. This is a feature for an operator, a misfeature for
|
||
an activist evading correlation.
|
||
|
||
---
|
||
|
||
## Comparison matrix
|
||
|
||
Scoring legend: `✓` shipped & on by default, `~` partial / opt-in,
|
||
`✗` not provided, `n/a` not applicable to that distro's model.
|
||
|
||
| Axis | veilor-os | Stock Fedora KDE | Kicksecure | Tails | Qubes OS | secureblue |
|
||
|---|:---:|:---:|:---:|:---:|:---:|:---:|
|
||
| **Encrypted at rest by default** | ✓ (LUKS2 argon2id) | ~ (optional) | ✓ | n/a (amnesic) | ✓ | ✓ |
|
||
| **MAC enforcing OOTB** | ✓ (SELinux + AppArmor v0.5) | ✓ (SELinux) | ✓ (AppArmor) | ✓ (AppArmor) | ✓ (per-VM) | ✓ (SELinux) |
|
||
| **Default-deny firewall** | ✓ | ✗ | ✓ | ✓ (Tor-only) | ✓ | ✓ |
|
||
| **USB default-block** | ✓ (USBGuard) | ✗ | ✓ | ✓ | ✓ (sys-usb) | ✓ |
|
||
| **Per-app isolation (VM/sandbox)** | ✗ | ✗ | ✗ | ~ (AppArmor) | ✓ (Xen VMs) | ~ (Flatpak/bwrap) |
|
||
| **Anonymity / Tor by default** | ✗ | ✗ | ✗ | ✓ | ~ (Whonix VMs) | ✗ |
|
||
| **Daily driver target (persistent)** | ✓ | ✓ | ✓ | ✗ | ✓ (heavy) | ✓ |
|
||
| **Signed releases (publisher key)** | ✓ (v0.4) | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||
| **Threat model published** | ✓ (this doc) | ✗ | ✓ | ✓ | ✓ | ✓ |
|
||
| **Hardware compatibility (laptops)** | ✓ (Fedora kernel) | ✓ | ~ | ~ (live USB) | ~ (Xen-pinned) | ✓ |
|
||
|
||
---
|
||
|
||
## Where veilor-os fits
|
||
|
||
Pick veilor-os if your job is to write code, edit docs, manage
|
||
infrastructure, read mail, browse — and you want a desktop that won't
|
||
quietly betray you to a generic adversary while you do it. **You are the
|
||
user, not the target of a state.**
|
||
|
||
Pick **Tails** for amnesia and Tor by default. **Qubes** if you must assume
|
||
any app could be compromised. **Kicksecure** for similar hardening on
|
||
Debian. **secureblue** for a hardened atomic Fedora. **Stock Fedora KDE**
|
||
if you just want Fedora with no opinions.
|
||
|
||
---
|
||
|
||
## v0.7 public-launch checklist
|
||
|
||
These are the items that gate flipping the repo public and posting:
|
||
|
||
- [ ] Threat model finalised and published (this document).
|
||
- [ ] GPG-signed releases working (v0.4 dependency — ISO + sha256 + .asc).
|
||
- [ ] Reproducible build verifiable from clean checkout (v0.4).
|
||
- [ ] mkdocs-material (or Hugo) site live on `veilor.org`, generated from
|
||
`docs/`. INSTALL, HARDENING, BUILD, ROADMAP, RELEASE, THREAT-MODEL,
|
||
CONTRIBUTING all rendered.
|
||
- [ ] Comparison + benchmark numbers published (cold boot, idle RAM, idle
|
||
egress, suspend/resume) vs stock Fedora KDE.
|
||
- [ ] Press kit page: wallpapers, logo SVG, screenshots, feature
|
||
one-liner, signed quotes from early users.
|
||
- [ ] **"What veilor-os is not"** preempt page — direct link from launch
|
||
post. Answers "why not Qubes?", "why not Tails?", "why not just
|
||
stock Fedora?" so the first hundred comments don't have to.
|
||
- [ ] Comparison post drafted for **r/linux**, **r/Fedora**, **HN**.
|
||
Same body, three formats. Lead with the threat model link, not the
|
||
black wallpaper.
|
||
- [ ] CHANGELOG.md tagged at v0.7.0 release commit; GitHub Release
|
||
created with ISO + sha256 + .asc artefacts attached.
|
||
- [ ] Repo flipped to public, `veilor.org` DNS pointed at the docs site,
|
||
Mastodon / Matrix / SimpleX announcement queued.
|
||
|
||
---
|
||
|
||
*Last reviewed: v0.7 draft. Update every minor release.*
|