left4me/docs/superpowers/specs/2026-05-15-session-handoff.md
mwiegand 1df811e62a
spec(hardening): threat model + defenses survey + test plan; pivot handoff
Reframe the queued uid-split decision into a broader hardening analysis.
Audit found the same-uid attack surface (DB readable from srcds, ptrace
allowed, RCON stored plaintext) is closable by either uid split or
systemd directive composition; the three specs ground that choice in a
threat model, survey the defenses, and lay out a self-contained test
plan to run on left4.me next. uid-split spec deferred pending results.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 13:07:40 +02:00

114 lines
5.6 KiB
Markdown

# Session handoff — next: execute hardening test plan
Short handoff. Three new hardening specs landed today; the next session
takes the test plan to `left4.me` and runs it. Decision on
`2026-05-15-user-uid-split-design.md` is **deferred** until the test
plan reports back.
## What just landed
Three coordinated specs at `docs/superpowers/specs/`:
- `2026-05-15-hardening-threat-model.md` — assets, attackers (A1-A6),
trust boundaries (TB1-TB8), attack scenarios (S1-S6), what we
defend (D1-D7), what we accept losing.
- `2026-05-15-hardening-defenses-survey.md` — full Linux + systemd
defense menu, per-defense primitive mapping, candidate composition
for `left4me-server@.service` + `left4me-web.service`.
- `2026-05-15-hardening-test-plan.md` — 11 tests runnable cold on
`left4.me`; drop-in style so they never modify persistent units.
## Why the shape changed (from uid-split → hardening)
The prior handoff pointed this session at the 1/2/3-user decision in
`2026-05-15-user-uid-split-design.md`. Audit during this session
established that the same-uid attack surface (DB readable from srcds,
ptrace of gunicorn allowed, RCON passwords stored plaintext in DB,
no `/proc` isolation) is closable by *either* a uid split *or*
systemd directive composition (`TemporaryFileSystem=` +
`SystemCallFilter=~@debug` + `PrivateUsers=true` + `ProcSubset=pid`
+ empty `CapabilityBoundingSet=`). Operator chose to step back: do
threat-model + research + test before committing to either approach.
The three new specs are the output of that step-back.
## What's next: run the test plan
The test plan is **self-contained** — drop a fresh Claude session on
`left4.me` (141.95.32.8) with the spec in hand and it can execute end
to end. System units only; no user units, no lingering.
Per the test plan's structure:
1. Capture baseline (`systemd-analyze security`, current unit state,
sysctl).
2. Tests 1-6 isolate individual directives against srcds on
`left4me-server@1` (canary; server@2 stays baseline as a fallback).
3. Test 7 composes everything that passed.
4. Test 8 verifies the threat-model defenses (D1-D5) actually work.
5. Test 9 applies `kernel.yama.ptrace_scope=2` system-wide.
6. Test 10 applies the sudo-compatible subset to `left4me-web.service`.
7. Test 11 is a 24-48h soak.
Results template at the bottom of the test plan; fill in as you go.
After execution: write the implementation plan at
`docs/superpowers/plans/2026-MM-DD-hardening-refactor.md` against the
proven composition. The plan touches `~/Projekte/ckn-bw/bundles/left4me/metadata.py`
(live source for unit emission per `items.py:2-5`) and the reference
copies in `deploy/files/usr/local/lib/systemd/system/`.
## Decision-relevant context
- **Source of truth for unit files is ckn-bw**, not left4me's
`deploy/files/`. The `deploy/files/usr/local/lib/systemd/system/*.service`
copies are reference-only post-deploy-dir-rethink; the
`systemd/units` reactor in `~/Projekte/ckn-bw/bundles/left4me/metadata.py:150+`
is the live emission. Audit confirmed (commit `5284e28` + `items.py:2-5`
comment).
- **Sandbox is already strong.** `l4d2-sandbox` unit is not in scope
for this refactor — its hardening profile was verified during 2026-05-15
build-time-idmap work. Document as load-bearing; do not weaken.
- **Sudo on the web app blocks deep hardening there.** `NoNewPrivileges=true`
and `PrivateUsers=true` are incompatible with the helper-invocation
pattern. Sudo-compatible subset only on web. Full hardening blocked
on a future "replace sudo with systemctl-managed unit triggering"
refactor (build-overlay-unit spec is a step in that direction).
- **uid-split spec is deferred, not closed.** After Phase A test
results come back, decide: residual risk small enough → close
`2026-05-15-user-uid-split-design.md` as superseded. Residual risk
significant → write the split as a follow-up.
## Open questions to clarify with operator before/during execution
(Captured in the threat model's "Open questions" section.)
1. Is gunicorn directly internet-reachable, or only via nginx?
2. Admin-auth strength on the web app (defines S2 realism).
3. Workshop content curation policy (defines A3 realism).
4. Is `ckn@10.0.4.128` usable as a test bench, or is `left4.me` the
only deployment target? (Test plan currently assumes `left4.me`.)
5. Current `kernel.yama.ptrace_scope` setting on the host.
6. AppArmor enabled on host? (Default Debian: not enabled.)
## What's NOT next
- **build-overlay-unit refactor**
(`docs/superpowers/specs/2026-05-15-build-overlay-unit-design.md`).
Still queued; sequenced behind this. The hardening profile from
this work becomes the template for the build-overlay unit.
- **Pushing the ckn-bw `91b7265` commit.** Still unpushed; still safe.
Mentioned in the previous handoff; not a blocker.
- **uid-split implementation.** Deferred pending test results.
- **AppArmor profiles.** Listed in the defenses survey; deferred.
Revisit after Phase A if directive-only hardening leaves gaps.
## Pointers
- Test plan (the thing to execute): `docs/superpowers/specs/2026-05-15-hardening-test-plan.md`
- Threat model: `docs/superpowers/specs/2026-05-15-hardening-threat-model.md`
- Defenses survey: `docs/superpowers/specs/2026-05-15-hardening-defenses-survey.md`
- Original uid-split spec (deferred): `docs/superpowers/specs/2026-05-15-user-uid-split-design.md`
- Live unit emission: `~/Projekte/ckn-bw/bundles/left4me/metadata.py:150+`
- Reference units: `deploy/files/usr/local/lib/systemd/system/`
- Scratch plan from earlier this session
(`~/.claude/plans/docs-superpowers-specs-2026-05-15-sessio-cosmic-codd.md`)
is superseded by the three specs; safe to discard.