From 0342c7bb571dd468f928a2bf83b50f22315bbde2 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 5 Oct 2026 12:01:25 +0200 Subject: [PATCH] agent v0.146.0 CHANGELOG (released) Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- CHANGELOG.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4c5551..6ac2aa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,46 @@ +## v0.146.0 — the agent's root grants narrowed: exact sudo patterns, a root content checker, fixed files from the bundle, the signed update checked as root (R-861) (2026-10-05) + +Released by `scripts/release-agent.sh`: binary sha256 `b860af465076041e07f35fed1b12d64ae2b2985d8995f0ce167418d39c2b00d5`, +config bundle sha256 `161c737e523aa7910cf32ce41b83f989569bee55b8c5938e7211c92aef68548e`. **Order on a box: the signed +`agent_update` FIRST (the old bundle still grants the old flip), then the signed `agent_config_update`.** Between the +two (minutes) the new agent's checker calls are refused and retried; nothing is lost. After the bundle, an agent BELOW +0.146.0 cannot update itself on that box any more (the unsigned flip grant is gone) — deliver both together. + +Design: `felhom.eu/documentation/architecture/03-host-agent.md` §3.1 (new). Measured before the change (real sudo +1.9.16, a throwaway container): the v0.145.0 sudoers let **23 of 29** attack command lines through; v0.146.0 lets +**0** through and still allows all **64** commands the agent's capability check uses. + +- **Exact patterns.** A sudoers `*` in the arguments also matches spaces: `pct set [0-9]* -onboot 1` matched + `pct set 100 --dev0 /dev/sda -onboot 1` (a raw host disk for a guest), `mount --bind /mnt/*/felhom-data + /mnt/felhom-drives/*` matched a `..` path onto `/etc/sudoers.d`, `nft add element … *` took a chained `; flush + ruleset`. Every varying argument list is now a sudo regex (`^…$`): one value per slot, a fixed character set, no + `..`, no extra argument. `TestSudoersRefusesTheR861Injections` (29 attacks) + `TestManifestCoveredBySudoers` + (regex-aware now). +- **`felhom-priv-apply`** (new root wrapper, in the bundle). A systemd mount/automount unit, a dnsmasq drop-in, the + WireGuard config and the OOB sshd config + felhom-op key reach their root-read places only through it: fixed source, + fixed destination, CONTENT checked against what the agent's renderers write (no `[Service]`, `Where=` only + `/mnt/` or `/mnt/felhom-drives/` and equal to the unit name, no `bind`/`suid`; a network share must carry + `nosuid,nodev`; no `dhcp-script=`; no `PostUp=`; the sshd config only the one template with its Port). Its 31 tests + (`configs/test_felhom_priv_apply.py`) + Go contract tests feeding each renderer's real output + (`internal/privapplytest`). Pre-flight: every live file on both demo boxes reads OK. +- **NFS/SMB options gain `nosuid,nodev`** (a set-uid file on a server outside the box never acts on the host). +- **Fixed files from the bundle.** The guest pre-start hook (`/var/lib/vz/snippets/felhom-guest-hook.sh`, run as root at + every guest start) and the shared drive parent script + unit are bundle files now (byte-identical to the agent's + constants, pinned). The agent no longer installs them from `/tmp`; it checks them (`guesthook.SnippetReady`, + `ensureSharedParentBoot`) and only registers / enables. +- **The signed update is checked as root.** `felhom-os-apply` mode `agent_update` verifies the operator signature + (root-owned signers, this host, the window, the nonce), re-hashes the staged binary against the SIGNED sha, then runs + the A/B flip; `felhom-selfupdate-guarded apply` is no longer in the agent's sudoers. 7 tests (`AgentUpdate`). +- **The root escrow run reads no path from the agent's config.** As root it pins the PVE secret dir and the WireGuard + state dir to their defaults, refuses a storage id that is a path, and reads its two staged files without following a + symlink (`readStagedNoFollow`) — before, a symlink in the agent's own directory sealed any root file into the blob. +- **Not narrowed here (named in `03` §3.1):** `FELHOM_CONTROLLERSWAP` stays guest-scoped (a compromised agent can run a + chosen controller image in the guest — the household's data, not host root); `FELHOM_ESCROW` still hands the agent R + by design (the agent relays the ceremony); the mkfs / pbs-apply / backup-target wrappers keep a coarse argument and + their own checks. +- Red-proofs F1–F9: `felhom.eu/documentation/audits/hub-safety-2026-10-05/partF/red-proof.txt` (F1's first run did NOT + convict — the name rule masked it — and the test now uses the pair only the Where rule stops). + ## v0.145.0 — the OS update repairs itself after a power cut; a short-session box gets restore-tested; "sent late" (R-876, R-874, R-875) (2026-10-05) Released by `scripts/release-agent.sh`: binary sha256 `894da35c7b9e1ac78885690b78352b634e6831e7d99b321573c75d878db8886e`,