# Aegis Linux — security model

Aegis is a security-forward Arch-based desktop, not a "secure operating system"
certification. This document states what the default baseline does, what it does
not protect against, and how to verify or recover it.

## 1. Default baseline

| Layer | What Aegis does |
|---|---|
| Disk encryption | LUKS2, AES-XTS-512, SHA-512, Argon2id, 3-second target. TRIM pass-through is off by default. |
| Layout | GPT ESP (1 GiB, unencrypted) + LUKS2 container. Btrfs subvolumes `@`, `@home`, `@log`, `@snapshots`. |
| Boot | UEFI only. systemd-boot by default, GRUB selectable. `sd-encrypt` in the initramfs. |
| Secure Boot | Opt-in, custom keys via `sbctl`, firmware Setup Mode only. Off by default. |
| Kernel | `linux` by default, `linux-hardened` selectable. Default cmdline includes `lockdown=integrity`, `init_on_alloc=1`, `init_on_free=1`, `slab_nomerge`, `vsyscall=none`, `audit=1`, `apparmor=1 security=apparmor`. |
| MAC | AppArmor enabled. Only the `aegis-mpv` and `aegis-imv` profiles are included; this is selected-profile confinement, not full-system confinement. |
| Firewall | nftables `inet` table, input policy `drop`, loopback and established/related allowed, rate-limited ICMP, logging. SSH is not opened. |
| Sysctl | Kernel pointer/dmesg restrictions, `kptr_restrict=2`, `dmesg_restrict=1`, `unprivileged_bpf_disabled=2`, Yama `ptrace_scope=2`, core dumps off, link/FIFO protections, reverse-path filtering, no redirects/source routing, syncookies. |
| Modules | Rare filesystems and legacy network protocols are disabled with `install ... /bin/false`; FireWire DMA is disabled. |
| Authentication | root locked; the first user is in `wheel`; sudo requires a password; pam_faillock (5 tries / 15 minutes); pam_pwquality minimum 12; `umask 027`; no passwordless sudo. |
| SSH | `openssh` installed but `sshd` disabled and masked. If enabled later: no root login, no password authentication, key-only, no X11 or agent forwarding. |
| Audit | auditd baseline rules for identity, sudo/PAM, SSH, modules, mounts, ptrace, time, kernel module changes, systemd units, firewall, and audit configuration. |
| DNS | systemd-resolved with DNS-over-TLS to Quad9 and Cloudflare, DNSSEC allow-downgrade. |
| Privacy | NetworkManager Wi-Fi scan randomization and stable per-network MAC addresses; Ethernet stable per-connection. |
| Packages | Arch package signatures required (`SigLevel = Required DatabaseOptional`). HTTPS-only reflector mirror ranking. Aegis local packages are unsigned but delivered on the signed ISO and never served from a remote unsigned repository. |
| Sandbox | `aegis-sandbox` uses bubblewrap for untrusted files; firejail is available. Neither is a complete desktop confinement system. |
| Updates | snap-pac pre/post snapshots, Snapper timeline/cleanup, weekly Btrfs scrub timer. |
| USB | USBGuard is installed but **disabled**. `aegis-usbguard-setup` generates a policy from currently connected devices and enables it only after confirmation. |
| Logs | journald persistent with a 500 MiB cap and 30-day retention; auditd; installer log. |
| Login | greetd + tuigreet; the session runs as the user, not root. |

## 2. Boot and disk

The ESP is not encrypted. It contains the kernel, initramfs, bootloader, and
systemd-boot entries. Without Secure Boot an attacker with physical access can
modify those files, although they still cannot read the LUKS2 root without the
passphrase. With Secure Boot enabled and Aegis keys enrolled, the bootloader and
kernels are signed and verified by firmware.

The LUKS2 passphrase is the recovery path even when TPM2 is enrolled. A firmware
update, Secure Boot key change, or TPM clear changes PCR 7 and breaks TPM2
auto-unlock; use the passphrase and re-run `aegis-enroll-tpm`. TPM2 enrollment is
skipped automatically when Secure Boot is selected during installation; enroll
after the Secure Boot state is final.

`lockdown=integrity` can block unsigned out-of-tree kernel modules (NVIDIA DKMS,
VirtualBox, some Wi-Fi drivers). The correct response is a separate
compatibility boot entry with `lockdown=none`, not editing the default entry.
Aegis does not silently weaken the default.

## 3. Authentication and privilege

- root is locked with `passwd -l root`. Recovery requires a live environment or
  a rescue shell, not a root password.
- The first user is in `wheel`. `/etc/sudoers.d/10-aegis` grants
  `%wheel ALL=(ALL:ALL) ALL`, which prompts for the user's password.
- `pam_faillock` uses `/etc/security/faillock.conf` (`deny=5`,
  `unlock_time=900`). `pambase` supplies the PAM stack on current Arch; Aegis
  does not patch the auth stack if `pam_faillock.so` is absent, and reports it.
- `pam_pwquality` enforces `minlen=12`, three character classes, no long
  repeats/sequences, and dictionary/user checks for interactive password
  changes. The installer enforces the same minimum at creation time.
- `umask 027` is set globally through `/etc/profile.d/99-aegis-umask.sh` and
  systemd's `DefaultUMask=0027`.
- Core dumps are disabled via `limits.d`, `coredump.conf`, and
  `kernel.core_pattern=|/bin/false`.

## 4. Network

nftables input policy is `drop`. The installed ruleset allows loopback,
established/related traffic, rate-limited ICMP/ICMPv6, and the small set of
multicast/DHCPv6 traffic needed for normal IPv6 operation. SSH port 22 is **not**
open. To enable SSH deliberately:

1. add the user's public key to `~/.ssh/authorized_keys` with mode 0600;
2. `sudo systemctl enable --now sshd`;
3. add an explicit rate-limited nftables rule, for example:
   `tcp dport 22 ct state new limit rate 3/minute accept`;
4. test from another machine before locking yourself out.

The SSH config in `/etc/ssh/sshd_config.d/10-aegis.conf` disables password and
root login and forwarding. `sshd` is masked by the hardening script, so
`systemctl enable sshd` is not enough until it is unmasked.

systemd-resolved uses DNS-over-TLS to Quad9 and Cloudflare. DNSSEC is
allow-downgrade because some networks break strict DNSSEC; this is a usability
trade-off. If a captive portal fails, inspect `resolvectl status` and use the
portal's DNS temporarily rather than disabling DoT permanently.

NetworkManager uses `wifi.scan-rand-mac-address=yes` and
`wifi.cloned-mac-address=stable`. This makes tracking across networks harder but
is not anonymity; the MAC is stable per network and the hostname, DHCP
fingerprint, and traffic patterns remain observable.

## 5. Application sandboxing

`aegis-sandbox` runs a command in a bubblewrap namespace with no network by
default, a read-only home, a private `/tmp`, and read-only system paths. GUI
viewers need the Wayland socket and GPU device, which the wrapper exposes.
Pass `--rw DIR` to grant writes and `--net` to share the network.

```bash
aegis-sandbox -- imv ~/Downloads/untrusted.png
aegis-sandbox --rw ~/Downloads -- imv ~/Downloads/untrusted.png
aegis-sandbox --net -- firefox
```

bubblewrap is not a full desktop sandbox: the process still runs as your user,
can read anything your user can read unless paths are masked, and the Wayland
socket allows input injection and screenshots according to compositor policy.
AppArmor profiles for mpv and imv are selected-profile confinement, not a
system-wide policy. Firejail's setuid model is documented by upstream and is not
enabled by default.

## 6. Updates and snapshots

Snapper is configured for `/` with timeline snapshots, cleanup, and the
`@snapshots` subvolume. snap-pac creates pre/post snapshots around pacman
transactions. The weekly `aegis-scrub.timer` verifies Btrfs metadata and data
checksums. Snapshots are not backups: a failing disk, lost LUKS header, or
corrupted pool can take the snapshots with it. Keep independent backups.

Aegis does not pin Arch package versions. A rolling update can change kernel,
firmware, or desktop behaviour. Reboot after kernel/systemd updates, verify the
boot entry, and keep a known-good snapshot. Local Aegis packages are rebuilt
from this repository and are not updated by `pacman -Syu` from a remote Aegis
repository.

## 7. Secure Boot and TPM2

Secure Boot is optional and off by default. Enrollment is offered only when
firmware reports Setup Mode. `sbctl enroll-keys --microsoft` keeps the Microsoft
certificates so option ROMs and third-party signed components continue to work.
Aegis signs systemd-boot (or GRUB) and the installed kernels. Re-sign kernels
after updates; `sbctl`'s pacman hook does this for files it manages.

TPM2 enrollment uses PCRs 0+7. PCR 0 covers firmware code; PCR 7 covers Secure
Boot policy and certificates. Firmware updates and Secure Boot changes break the
seal by design. The passphrase slot is never removed. `aegis-enroll-tpm`
replaces the TPM2 slot after a change.

## 8. Threat model

**Assets:** data at rest, credentials and keys, system integrity, boot chain,
network metadata, availability, and trust in updates.

| Adversary | Capability | Mitigations | Residual risk |
|---|---|---|---|
| Opportunistic thief | Powered-off laptop | LUKS2 Argon2id, locked root, screen lock, optional Secure Boot | Weak passphrase; unlocked/suspended device; ESP tampering without Secure Boot |
| Malicious local user | Non-root shell on a multi-user system | Permissions, sudo auth, faillock, audit, selected AppArmor profiles, no passwordless sudo | Kernel/module attack surface; user namespaces needed by sandboxing; session data |
| Network attacker | Same LAN or Wi-Fi | Default-deny inbound, DoT, MAC randomization, no open services, signed packages over HTTPS | Outbound exfiltration, captive portals, traffic analysis, upstream compromise |
| Malicious application | Runs as the user | bubblewrap/firejail, user separation, AppArmor where profiled, Wayland | Browser 0-day, XWayland, portal abuse, unconfined apps, readable user data |
| Evil maid | Physical access before boot | Optional Secure Boot, signed kernel, LUKS, unencrypted ESP | Firmware implants, TPM/PCR reset, no tamper-evident seal, Secure Boot off by default |
| Supply chain | Compromised mirror or package | Arch signatures, HTTPS, ISO signing, build record | Compromised Arch upstream, AUR packages, unsigned local Aegis packages, build host compromise |
| Remote attacker | Network reachability | No SSH by default, firewall, no exposed daemons | User-installed services, browser, kernel network stack |

## 9. Explicitly not protected

Aegis does **not** protect against:

- data while the system is unlocked, suspended, or running;
- root-level compromise, malicious kernel modules, or malicious firmware;
- cold-boot, DMA, or side-channel attacks;
- hardware keyloggers or compromised peripherals;
- evil-maid attacks when Secure Boot is disabled or firmware is compromised;
- compromised Arch infrastructure or malicious AUR packages;
- metadata and traffic analysis, browser fingerprinting, or a compromised
  network;
- multi-user hostile environments where users can attack each other;
- hibernation (not configured) or unencrypted swap (zram only);
- loss of independent backups;
- TPM2 PCR brittleness after firmware or Secure Boot changes;
- unencrypted ESP contents (kernel/initramfs are visible; integrity requires
  Secure Boot);
- any claim of "unbreakable" or "military-grade" security.

A clean `aegis-selftest` is evidence about configuration, not a guarantee that a
machine is uncompromised.

## 10. Verify and recover

```bash
sudo aegis-selftest
sudo cryptsetup luksDump /dev/nvme0n1p2
sudo btrfs subvolume list /
sudo snapper -c root list
sudo nft list ruleset
sudo aa-status
sudo systemctl status nftables auditd apparmor
sudo journalctl -b -p err
```

Recovery paths:

- **Forgotten user password:** boot a recovery entry or live ISO, mount the
  encrypted root, `arch-chroot`, and `passwd user`.
- **TPM2 no longer unlocks:** enter the LUKS passphrase, boot, and run
  `sudo aegis-enroll-tpm`.
- **Secure Boot failure:** boot the recovery entry or disable Secure Boot in
  firmware; re-enroll and re-sign after restoring the correct keys.
- **Broken update:** boot a Snapper snapshot from the bootloader or restore it
  with `snapper rollback`.
- **Lost USB input after USBGuard:** stop USBGuard from a TTY and
  `usbguard allow-device <id>`; see `/usr/share/aegis/usbguard/README.md`.
- **Firewall mistake:** use a local TTY, `sudo nft list ruleset`, and restore the
  ruleset from `/etc/nftables.d/aegis.nft`. Do not disable the firewall
  permanently to work around a rule error.

## 11. Reporting

Security issues in Aegis-specific code should be reported privately to the
maintainer before public disclosure. Arch upstream package vulnerabilities
should go to the Arch security team and the upstream project. Aegis is not
affiliated with or endorsed by Arch Linux.
