5.3 KiB
The 20 catalog apps with a bad runtime inside (R-1332) — where each one stands, 2026-10-28
HTTP2Shell (CVE-2026-111497): the Brotli decoder in Node.js (fixed 22.23.4 / 24.22.1 / 26.12.1; 20, 23, 25 get no fix)
and Python brotli (fixed 1.0.10 / 1.1.1 / 1.2.1). Every version below was READ FROM THE IMAGE
(scripts/image_runtime.py: the registry config, then the layers — never release notes); the candidates came from each
registry's tag list in the pinned tag's own shape (rt-candidates.json, rt-candidates.txt). The main version is the
first number of the tag (the ladder's rule; 0.x moves by the minor were lane steps on 2026-10-27, e.g. Homebox
0.26 → 0.27). „Runs" = what the image starts (its config) and, on a test box, ps in the running container
(ps-test-boxes.txt). The setup gate covers an app only until its first account exists; the family gate always.
Fleet (2026-10-28): three boxes report — demo-hp, Tester 1, demo-felhom; no household. 9202 is scratch.
State 1 — a fixed release in the same main version: a security-fix step (8)
| App | Pinned → step | Runtime: pinned → step | Runs | Boxes | Walk |
|---|---|---|---|---|---|
| adventurelog | v0.13.0 → v0.13.1 (frontend + backend) | Node 26.3.0 → 26.12.1 | node start.js (SvelteKit server; ps on demo-hp) |
demo-hp | batch 1 |
| ghost | 6.67.0-alpine → 6.73.0-alpine | Node 22.23.3 → 22.23.4 | Node (Ghost) | — | batch 1 |
| metube | 2026.09.29 → 2026.10.27 | py-Brotli 1.2.0 → 1.2.1 | Python (aiohttp) | — | batch 1 |
| papra | 26.6.2-rootless → 26.7.1-rootless | Node 26.4.0 → 26.12.1 | Node | — | batch 1 |
| zipline | 4.8.0 → 4.8.2 | Node 24.21.0 → 24.22.1 (Alpine brotli-libs 1.2.1) | Node | — | batch 1 |
| karakeep | 0.33.2 → 0.34.1 | Node 24.18.1 → 24.22.1 | Node | — | batch 2 |
| tandoor | 2.6.15 → 2.7.2 | Node 24.18.1 → 24.22.1 (Alpine nodejs 24.22.1-r0) | Python (Django) + Node in the image | — | batch 2 |
| dawarich | 1.15.3 → 1.19.0 (app + sidekiq) | Node 20.19.2 → no Node in the image (Debian libbrotli1 1.1.0-2+deb13u1) | Ruby (Rails) | — | batch 2 |
(Home Assistant 2026.9.4 → 2026.10.4 and Immich v3.2.4 → v3.3.5 went live this morning — catalog b5b78f6, 0158b50.)
State 2 — the fix needs a new main version: a row each, no step today (4 apps + 1 box program)
| App | Pinned → fixed in | Runtime | Runs | Gate | Boxes |
|---|---|---|---|---|---|
| homepage | v1.13.2 → v2.x (v2.7.0) | Node 22.22.3 → 24.22.1 | node server.js as root |
family gate (always) | — |
| termix | 2.8.0 → the new numbering 26.10.x (26.10.5); 2.9.2 still Node 26.10.0 | Node 26.9.0 → 24.22.1 | Node | setup gate | — (D58: waits for its big step, R-1311) |
| wanderer | v0.20.0 → v0.21.2 | Node 22.23.1 → 22.23.4 | npm run start |
— | none; hidden since today (D59) — its big step (R-1313's successor row) |
| seerr | jellyseerr 2.7.3 → upstream moved to ghcr.io/seerr-team/seerr (v3.5.1) |
Node 22.18.0 → 22.23.4 | pnpm start (Node) |
setup gate | — |
| filebrowser (a BOX program, not an app) | 1.5.8-stable → 2.0.2-stable | Alpine brotli-libs 1.2.0-r1 → 1.2.1-r0 | a Go binary that does NOT link libbrotli (ldd: musl only; no process maps it — all three boxes, filebrowser-brotli.txt); brotli-libs is there for libcurl |
the controller's own route | all three boxes |
State 3 — no fixed release exists (the watch keeps flagging them every night) (6)
| App | Pinned (newest) | Runtime | Runs | Gate | Boxes |
|---|---|---|---|---|---|
| actualbudget | 26.9.0 (26.10.0 still Node 24.21.0) | Node 24.20.0 | node app.js |
setup gate | — |
| calcom | v6.2.0 (newest) | Node 20.20.0 (end of life — no fix on its line) + Debian 12 libbrotli1 1.0.9-2+b6 | Node (start.sh) |
setup gate | — (R-1329) |
| calibre-web | v4.0.8 (newest) | py-Brotli 1.2.0 (+ Pillow's libbrotlidec 1.2.0, Debian libbrotlidec 1.1.0) | Python cps.py loads all three (its /proc/<pid>/maps, read from the guest — calibre-web-brotli.txt; a morning line here said „not loaded" from the process list: wrong, corrected the same day). The Python decoder is urllib3's, for replies to the app's own outbound calls (book metadata) |
— | demo-hp |
| paperless-ngx | 2.20.15 (3.3.4 still py-Brotli 1.2.0, and a new main) | py-Brotli 1.1.0 | Python; decodes only replies to its own outbound calls (R-1331, decided) | — | demo-hp, Tester 1 |
| romm | 5.4.1 (newest) | Node 24.18.1 | no Node process (gunicorn, rq, nginx — ps on demo-hp) |
setup gate | demo-hp (D61 = keep offered, R-1330) |
| sparkyfitness | v0.17.3 (v1.9.0 still Node 24.22.0, and a new main) | Node 24.18.0 | tsx index.ts (Node) |
setup gate | — |
(SparkyFitness has two images; its web image is nginx and carries no Node.)
Exposure, in plain words
A bad decoder is dangerous when the app unpacks Brotli data that an attacker chose: a request body sent with
Content-Encoding: br, or the reply of a server the attacker controls. In every app here the household's login (or the
family gate) stands in front of the app's own pages after setup; a Node server that unpacks request bodies, or that
fetches outside pages for its users (bookmarks, recipes, link previews — Karakeep, Tandoor, Adventurelog), is the
likelier path. No app here has a notice of its own: the watch is the only thing that sees them.