From 03fcc6e11741cd959bb667073155cde160fb2fc8 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Mon, 13 Apr 2026 23:19:38 +0200 Subject: [PATCH] Document app container architecture and socket proxy requirement - TODO: add app container architecture section with socket proxy, network isolation, image allowlist, and Podman evaluation items - security-auditor: hard rules for never mounting raw Docker socket and never spawning privileged containers Co-Authored-By: Claude Sonnet 4.6 --- .claude/agents/security-auditor.md | 2 ++ TODO.md | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/.claude/agents/security-auditor.md b/.claude/agents/security-auditor.md index d1f7ef4..026c23f 100644 --- a/.claude/agents/security-auditor.md +++ b/.claude/agents/security-auditor.md @@ -83,3 +83,5 @@ Key management: private key (`JWT_PRIVATE_KEY`) signs tokens and must never be e - Never use `text()` with string interpolation in SQLAlchemy queries - Never expose `hashed_password`, `is_superuser`, or internal IDs in API responses unless explicitly required - After any code change, verify the pre-commit hook still passes +- **Never mount `/var/run/docker.sock` directly into the backend container** — Docker socket access must always go through `tecnativa/docker-socket-proxy` on an internal-only network with a minimal API whitelist. Raw socket access inside any app container is equivalent to root on the host. +- **Never spawn `--privileged` containers** or containers with added capabilities for app workloads diff --git a/TODO.md b/TODO.md index a834f02..7872cdf 100644 --- a/TODO.md +++ b/TODO.md @@ -25,6 +25,16 @@ - [x] **Profile page** (`/profile`) — shows personal information for the logged-in user - [x] **Edit & save profile** — form to update personal details, stored in a dedicated `profiles` table (separate from `users`, same PostgreSQL container) +## App container architecture (future) + +Design decision: each installable app (billing, PDF, email, etc.) runs in its own isolated Docker/Podman container, spawned and managed by the backend via the Docker API. Key rules to implement: + +- [ ] **Docker socket proxy** — backend must never mount `/var/run/docker.sock` directly; use `tecnativa/docker-socket-proxy` on an internal-only network, with only the required API endpoints whitelisted (CONTAINERS, IMAGES, NETWORKS, POST). Raw socket access = root on the host. +- [ ] **Network isolation per app** — each spawned app container gets its own Docker bridge network; app containers never talk to each other directly; only the backend can reach them +- [ ] **No privileged app containers** — all spawned containers run without `--privileged`, without extra capabilities, with resource limits (CPU, memory) +- [ ] **Image allowlist** — backend may only spawn containers from a pre-approved image list; never pull or build arbitrary images at runtime +- [ ] **Consider Podman** — evaluate rootless Podman as replacement for Docker daemon; daemonless model eliminates the socket entirely; Docker SDK compatible + ## Infrastructure - [ ] **Docker port hardening** — expose only port 80 externally; backend (8000) and db (5432) must not be reachable from outside the Docker network. Prepare for deployment behind Traefik or nginx proxy manager (SSL termination, reverse proxy, no direct container exposure).