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>
5.6 KiB
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 forleft4me-server@.service+left4me-web.service.2026-05-15-hardening-test-plan.md— 11 tests runnable cold onleft4.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:
- Capture baseline (
systemd-analyze security, current unit state, sysctl). - Tests 1-6 isolate individual directives against srcds on
left4me-server@1(canary; server@2 stays baseline as a fallback). - Test 7 composes everything that passed.
- Test 8 verifies the threat-model defenses (D1-D5) actually work.
- Test 9 applies
kernel.yama.ptrace_scope=2system-wide. - Test 10 applies the sudo-compatible subset to
left4me-web.service. - 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/. Thedeploy/files/usr/local/lib/systemd/system/*.servicecopies are reference-only post-deploy-dir-rethink; thesystemd/unitsreactor in~/Projekte/ckn-bw/bundles/left4me/metadata.py:150+is the live emission. Audit confirmed (commit5284e28+items.py:2-5comment). - Sandbox is already strong.
l4d2-sandboxunit 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=trueandPrivateUsers=trueare 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.mdas 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.)
- Is gunicorn directly internet-reachable, or only via nginx?
- Admin-auth strength on the web app (defines S2 realism).
- Workshop content curation policy (defines A3 realism).
- Is
ckn@10.0.4.128usable as a test bench, or isleft4.methe only deployment target? (Test plan currently assumesleft4.me.) - Current
kernel.yama.ptrace_scopesetting on the host. - 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
91b7265commit. 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.