veilor-os/docs/research/2026-05-05-agent-wave/04-hardening-tier-2.md
veilor-org 49a2e2557e docs: 9-agent research wave findings — v0.5.32 blocker map
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.
2026-05-05 14:52:53 +01:00

5.1 KiB
Raw Blame History

Hardening tier 2 — concrete plan

Agent 4 of 9-agent wave, 2026-05-05.

Repo state already in tree

  • scripts/apparmor/ ships 3 profiles (thorium, veilor-power, lm-studio) — complain-mode, not auto-loaded. No browser/mail /Element profile.
  • scripts/selinux/ ships custom .te modules — primary MAC.
  • overlay/etc/audit/plugins.d/veilor-remote.conf + audisp-remote.conf.disabledscaffold present, opt-in switch missing.
  • kickstart/veilor-os.ks — single live-ks. Real LUKS install lives in overlay/usr/local/bin/veilor-installer (generates ks at runtime).
  • No nftables overlay. No homed scaffold. No veilor-audit-shipping CLI.

Item-by-item plan

1. AppArmor stack with SELinux — M

Fedora 43 ships apparmor-parser/libapparmor. Kernel has both LSMs. Stacking works since 5.1; SELinux stays primary, AppArmor confines specific binaries by path. No conflict — they layer. Risk: AA profiles based on Debian/Ubuntu paths fail on Fedora.

Files:

  • kickstart/veilor-os.ks %packages add apparmor-parser apparmor-utils apparmor-profiles
  • overlay/etc/apparmor.d/veilor.d/ (new) — vendor profiles firefox, thunderbird, element-desktop, signal-desktop
  • scripts/40-apparmor.sh (new) — parses + sets all veilor profiles to complain on first install (logs only, no break)
  • overlay/usr/local/bin/veilor-doctor — adds AA status check

Test: aa-status | grep complain shows >=4 loaded; firefox writes outside policy → audit.log denial.

2. systemd-homed opt-in — L

Default LUKS storage homectl drops key on suspend; resume needs PAM unlock again — breaks "lid open, keep working". Use --storage=fscrypt on top of existing btrfs /home subvol — suspend transparent, encrypts at rest with per-user key.

Files:

  • overlay/usr/local/bin/veilor-homed-enable (new) — confirms warning, runs homectl create admin --storage=fscrypt --real-name="veilor admin" after migrating files
  • overlay/etc/pam.d/sddm drop-in for pam_systemd_home.so
  • doc in docs/HARDENING.md. Not auto-run — only via post-install.

3. nftables alongside firewalld — S

firewalld speaks nftables backend on F43 — they don't conflict; firewalld owns inet firewalld table. veilor-os preset = separate inet veilor table loaded by its own service.

Files:

  • overlay/etc/nftables/veilor.nft (new) — table inet veilor: ssh per-IP rate limit (5/min), ICMP rate limit, optional ip6 daddr ::/0 drop toggled by sysctl-style /etc/veilor/ipv6.disabled, anti-port-scan via meter set
  • overlay/etc/systemd/system/veilor-nftables.service (new) — After=firewalld.service
  • kickstart/veilor-os.ks %packages add nftables, services-enabled add veilor-nftables

Test: nft list ruleset shows both firewalld AND veilor; hping3 -S -p 22 --flood from second VM gets rate-limited.

4. Audit log shipping — S

Plumbing already in tree (audisp-remote.conf.disabled, veilor-remote.conf with active=no). What's missing: CLI to flip the switch with cert pinning.

Files:

  • overlay/usr/local/bin/veilor-audit-shipping (new)
    • enable HOST PORT FINGERPRINT writes /etc/veilor/audit-pin.sha256, copies audisp-remote.conf.disabledaudisp-remote.conf with substituted host/port, enables plugin (active=yes), restarts auditd
    • disable reverses
  • audisp-remote speaks TLS directly; cert pinning via verify_peer=yes
    • peer_cert_fingerprint
  • Use self-signed pinned, not LE — collectors are LAN/VPN

Test: stand up rsyslog listener on nullstone with self-signed cert; run helper; trigger sudo -i; tail nullstone for AUTHPRIV event; revoke cert → events stop with logged TLS error.

5. Installer kickstart split — needs re-scope, S

Roadmap item is stale. As of v0.5.30 we already do real LUKS+btrfs in veilor-installer which generates ks at runtime. Re-scope: extract that generated ks template into static kickstart/veilor-os-install.ks (parameterised via %include /tmp/answers.ks), so reviewable in repo and reusable headlessly.

Files:

  • split overlay/usr/local/bin/veilor-installer heredoc into kickstart/veilor-os-install.ks
  • installer just writes answers + cp the ks
  • CI lints both with ksvalidator

6. Audit baseline re-run — S

Mechanical: cp security/audit-template.md security/veilor-os-distro/2026-05-DD.md, run on VM, target lower findings count than v0.2's baseline.

Order, dependencies, ship plan

Dependencies: (5) blocks (6) — audit a stable installer, not a moving heredoc. Else parallel.

Total effort: 2S + 1S(rescope) + 1S + 1M + 1L ≈ 57 dev-days.

  • v0.5.32 (small wins): (4) audit shipping CLI + (3) nftables preset. Both S, scaffold completion, pure overlay (no kickstart risk).
  • v0.5.33: (5) ks split + (6) audit baseline re-run.
  • v0.6 (medium): (1) AppArmor stack — package install + 4 profiles
    • doctor integration; complain-mode keeps blast radius zero.
  • v0.7 (big lift): (2) systemd-homed — UX-disruptive, needs migration helper + doc page + suspend/lock/swap testing.