Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8553,6 +8553,67 @@ NET_BIND_SERVICE. The failure mode is nasty: **Next.js keeps serving on
502s.** Same entrypoint pattern that bit Donetick and Tududi. Add the caps
from the start on any image using supervisord + nginx.

### Weekly CVE pass, 2026-08-09 (334 new findings) — one bump survived

Trivy flagged 334 findings across 16 images (159 "fixable"). Applying last
week's verify-before-bumping method — scan the old AND new artifact, keep
only what reduces findings — **exactly one bump survived out of nine
candidates with newer artifacts**:

| Candidate | Verdict |
|---|---|
| **uptime-kuma 2.4.0 → 2.5.0** | **KEPT** — fixes CVE-2026-12143/-12151/-67214, introduces nothing. Note: last week's 2.5.0 build was CVE-identical and rejected; this week's *rebuild* of 2.5.0 carries the fixes. Version and digest move independently — check both |
| fizzy (rebuild) | identical: 76/13/76 both sides |
| hedgedoc 1.11.1 (rebuild) | identical: 28/7/25 |
| karakeep (rebuild) | identical (+1 uHIGH) |
| litellm v1.94.0 → v1.95.0 | identical: 5 fixable both — version bump, zero CVE value |
| tailscale v1.98.10 → v1.102.2 | identical: 2 both |
| ghost, traffic-analytics 1.0.329 | identical |
| mysql 8.4.10 → 8.4.11 | identical: 21 both. **`mysql:latest` scanned 18 but is MySQL 26.7.0** — an innovation-release major jump for a −3 count; not a serious option for Ghost's LTS database |

No newer artifact at all (their "fixable" waits on upstream rebuilds):
super-productivity, paperless, postgres:17-alpine, bookstack, wanderer-web,
immich-server, apprise.

**Mitigation half.** The 38 unfixed CRITICALs sit in the four new apps, all
already LAN/tailnet-gated at Caddy. Reachability checked per app:

- **fizzy — genuinely reachable, now hardened.** Its criticals include
libraw, OpenEXR and ImageMagick, which decode **attacker-supplied images**
— uploading images to cards is what Fizzy is for. It had **zero**
hardening. Now `no-new-privileges` + bare `cap_drop: ALL` (verified safe:
the image runs as `rails` uid 1000 from PID 1, no root-then-drop, no
privileged port — checked with `podman top`, not assumed) + limits sized
from measured steady state (3.75 GB/151 PIDs → 6g/512).
- **super-productivity — unreachable furniture, hardened anyway.** Its
criticals are the perl-base cluster + libxml2 in a container that serves a
static SPA. nginx binds :80 as root then drops, so it gets the
root-then-drop cap set + NET_BIND_SERVICE (the nimbus lesson), 256m/128.
- **paperless, docs (HedgeDoc)** — already hardened at deployment
(cap_drop/no-new-privileges/limits present), already gated. Their perl/
image-lib criticals are the same base-furniture cluster; paperless *does*
decode documents, but its consumer already runs under the existing caps.
- **postgres:17-alpine** — same story as 16.14-alpine last week: Go stdlib
CVEs in a helper binary, nothing actionable here.

Deploys verified: uptime-kuma healthy with 62 heartbeats in 2 minutes;
fizzy healthy with secrets confirmed non-blank after redeploy
(`SECRET_KEY_BASE` length checked inside the container — the blanked-secrets
failure mode is real, see the pass-deploy notes); sp healthy and serving.

**Operational note:** the repo+tag scan keying means the uptime-kuma bump
creates a new state key (`:2.5.0-slim-rootless`), so the next scan re-reports
that image's full finding set once and prunes the 2.4.0 key. Expected, per
the keying design — not a regression.

**pass-cli session wedge seen during deploy:** `pass-cli info` failing with
"Error getting personal access token name" while `pass-cli login` says
"Already authenticated" means the scratch session dir is corrupt. Fix:
`rm -rf /tmp/pass-agent-selfhosted/.session` and rerun — the durable PAT
re-authenticates. A deploy in this state emits "variable is not set"
warnings for EVERY Pass field; a single missing-field warning (e.g.
`SMTP_USERNAME`, genuinely absent from the item) is normal.

### Branch protection + required CI (GitHub)

Nothing lands on `main` — not even from the repo owner, not even from an
Expand Down
20 changes: 20 additions & 0 deletions fizzy/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ services:
image: ghcr.io/basecamp/fizzy@sha256:c0aadd02a8249752998d3fe930ce99e24de6997522511ee052d1bb44616ac521
container_name: fizzy
restart: unless-stopped
# Hardening added 2026-08-09 (weekly CVE pass). Fizzy carries 13 unfixed
# CRITICAL findings, and unlike most of the estate's perl-base noise,
# several are genuinely reachable here: libraw, OpenEXR and ImageMagick
# decode ATTACKER-SUPPLIED images — uploading images to cards is exactly
# what Fizzy is for. No patched build exists (the 2026-08-09 rebuild was
# scanned and is CVE-identical), so this caps the blast radius instead:
# a crash or exploit attempt stays a contained restart.
#
# A bare `cap_drop: ALL` with NO cap_add is deliberate and verified: the
# image runs as `rails` (uid 1000) from PID 1 — there is no root-then-
# drop entrypoint (checked with podman top, unlike nimbus/donetick), and
# thruster binds 8080, puma 3000, both unprivileged.
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
# Steady state measured at 3.75 GB / 151 PIDs (Rails + SolidQueue
# workers) — limits sized ~1.6x so normal operation never trips them.
mem_limit: 6g
pids_limit: 512
# Do NOT set `user:` — on podman-machine (macOS) the container's root maps
# to the host user, giving sane ownership on the bind mount below. Same
# reasoning as copyparty's and Ghost's compose.yaml.
Expand Down
25 changes: 25 additions & 0 deletions super-productivity/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ services:
image: docker.io/johannesjo/super-productivity@sha256:ae91fe9ac19561e0f3669d15a2c4c71d7a75c43a29eb44ddc010ae50d1f63c82
container_name: super-productivity
restart: unless-stopped
# Hardening added 2026-08-09 (weekly CVE pass). This image's 5 unfixed
# CRITICALs are the estate-wide perl-base cluster plus libxml2 — base
# furniture in a container that only serves a static SPA via nginx, so
# none of it is in the request path. Hardening is defence in depth, not
# a response to reachable risk.
#
# Capability set verified against the running container (podman top):
# nginx master runs as root and drops to the `nginx` user, and binds :80
# INSIDE the container (3601 is the host side) — so this needs the
# root-then-drop set plus NET_BIND_SERVICE. A bare `cap_drop: ALL`
# breaks this shape of image — see the nimbus note in SETUP.md.
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- DAC_OVERRIDE
- FOWNER
- SETGID
- SETUID
- NET_BIND_SERVICE
# Steady state measured at 12 MB / 6 PIDs — a static file server.
mem_limit: 256m
pids_limit: 128
environment:
# The image's entrypoint templates nginx's config from this; 80 is its
# own default, stated explicitly so the port mapping below is readable
Expand Down
8 changes: 7 additions & 1 deletion uptime-kuma/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@
# wants to fire a notification without embedding a webhook URL of its own.
services:
uptime-kuma:
image: louislam/uptime-kuma:2.4.0-slim-rootless@sha256:8f5c20a6002de53f8ed8a9b744ea08f566cfb690e5bbbfc1c278483aaf374992
# 2026-08-09 CVE pass: 2.4.0 -> 2.5.0. Verified by scanning both digests
# before bumping: fixes CVE-2026-12143, CVE-2026-12151 and CVE-2026-67214,
# introduces nothing (86 -> 83 fixable, unfixed unchanged). Note last
# week's 2.5.0 build was CVE-identical to 2.4.0 and was rejected; this
# week's REBUILD of 2.5.0 is what carries the fixes — version and digest
# move independently, so both were checked.
image: louislam/uptime-kuma:2.5.0-slim-rootless@sha256:37894805e7df2211dc2c69374034849c9a73efd8dd55469953261cafda091bc4
container_name: uptime-kuma
restart: unless-stopped
volumes:
Expand Down