This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
# Security review 2026-10-12 — coverage
|
||||
|
||||
Each area: what was checked and holds, what fails (→ finding), and what was not reviewed.
|
||||
|
||||
| area | checked and holds | fails | not reviewed |
|
||||
|---|---|---|---|
|
||||
| C1 box from the internet | bcrypt passwords; host-only dashboard cookie; two CSRF mechanisms cover every state-changing route except one GET (SR-16); visitor address read from the right; traefik strips client-written forwarding headers; traefik dashboard not exposed; gate tokens one-use, host-bound, 60 s; family-gate exceptions anchored | SR-03, SR-09, SR-10, SR-16 | catalog apps changed before 2026-09-28 (FIRST-ADMIN.md covers them) |
|
||||
| C2 hub from the internet | per-box keys compared in constant time; cross-box checks on every box route (14 with tests, 5 new tests); appliance register rate-limited | SR-01, SR-02, SR-08, SR-22, SR-23 | the claim engine; the `/bind` page's guessing limits; server-side fetches beyond Cloudflare and Gitea; live cross-box GETs (R-955) |
|
||||
| C3 controller → agent | every local-API route bound to the token's own guest; tokens 256-bit and stored hashed; listens on the island bridge; 64 KiB body cap; the July audit's A1, B1, D3 fixed | SR-06, SR-11, parts of SR-17 | — |
|
||||
| C4 hub → agent | verify order namespace → allow-list → crypto → target → time → nonce; nonce store on disk and pruned only after expiry; unsigned hub jobs reach no destructive executor; desired state cannot destroy or change retention | parts of SR-17 (no size bounds, no maximum validity) | — |
|
||||
| C5 supply chain | agent binary and root files need an operator signature with sha256; OS updates are exact apt versions; installer checks agent, golden and bundle hashes; no other catalog template uses privileged mode, host networking or devices | SR-04, SR-12, SR-13, SR-14 | Gitea branch and tag protection (live); the CI runner as a push path; the golden image's start unit |
|
||||
| C6 secrets | escrow wraps the PBS key with PBS's own passphrase function; identity bundle with age; recovery code ~129 bits; the hub holds ciphertext only; host secret files 0600 (measured) | SR-08, SR-18, parts of SR-17 | the hub's request logging; export and debug bundles |
|
||||
| C7 host and guest | guest unprivileged; guest root password locked, key-only SSH (measured); operator SSH port reachable only through the tunnel (measured) | SR-07, SR-15, parts of SR-17 | restore of a privileged archive (Proxmox enforces it) |
|
||||
| C8 public sites | HSTS on all; Gitea sign-up disabled; anonymous Gitea package API refuses; no `.git` or `.env` on felhom.eu | — (four repositories are public: the operator's decision, R-925) | — |
|
||||
|
||||
Scanner coverage: `SCANNERS.md`. Not scanned: the 53 catalog app images (R-987).
|
||||
@@ -0,0 +1,50 @@
|
||||
# Security review 2026-10-12 — findings (short form, operator option A)
|
||||
|
||||
Reviewed: controller `dcd89364a4` · agent `86adbcaf8a` · felhom.eu `c9b9432986` · catalog `1a642b43e7`.
|
||||
For a finding that is still open, this page names the missing check only. Code paths, evidence and proposed tests for
|
||||
open findings are held off-git on DooPlex: `/mnt/5_hdd/felhom.eu/evidence/security-review-2026-10-12-PRIVATE/`.
|
||||
`second read` = a fresh subagent traced the claim on its own (holds / partly); `self` = re-read by the session.
|
||||
|
||||
| ID | area | finding | static / measured | tech sev | Sev | second read | row |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| SR-01 | hub | The hub's operator key was readable in public git history and still worked | measured | Critical | P1 | holds | R-950 (CLOSED: rotated) |
|
||||
| SR-02 | hub | Three hub read routes needed no credential | measured | High | P1 | holds | R-951 (CLOSED: hub 0.148.0) |
|
||||
| SR-03 | box | A box's own hub key can read and replace the box's settings file; no signature | static | High | P2 | holds | R-970 |
|
||||
| SR-04 | catalog | A catalog push reaches every box; the box does not check container privileges | static | High | P2 | holds | R-971 (decision) |
|
||||
| SR-05 | build | Shipped binaries on an unsupported Go; base images with fixable criticals | measured | High | P2 | self | R-972 |
|
||||
| SR-06 | agent | A compromised controller can force backups that prune older restore points | static | Medium | P3 | partly (local holds) | R-973 |
|
||||
| SR-07 | host | The PBS root wrapper acts as root on a folder the agent controls | static | Medium | P3 | self | R-974 |
|
||||
| SR-08 | hub | Customer tunnel, Cloudflare and git tokens unsealed in the hub database | static | Medium | P3 | self | R-975 |
|
||||
| SR-09 | box | Family session copied to apps; a password reset does not end family/gate sessions | static | Medium | P3 | self | R-976 |
|
||||
| SR-10 | box | FileBrowser default password can return; tunnel may start before the claim | static | Medium | P3 | self | R-977 |
|
||||
| SR-11 | agent | Re-running the escrow ceremony can void the written recovery code | static | Medium | P3 | self | R-978 |
|
||||
| SR-12 | updates | Controller updates trusted by tag only; unvouched tags offered | static | Medium | P3 | self | R-979 |
|
||||
| SR-13 | install | The installer and ISO cannot be checked as ours | static | Medium | P3 | self | R-980 |
|
||||
| SR-14 | catalog | homepage has the Docker socket and no login or gate | static | Medium | P3 | self | R-981 |
|
||||
| SR-15 | host | Root password SSH from the LAN | measured | Medium | P3 | self | R-982 |
|
||||
| SR-16 | box | Seven small dashboard weaknesses (redirect, GET reboot, framing, limiter, …) | static | Low | P3 | self | R-983 |
|
||||
| SR-17 | host | Nine small host/agent hardening items | static + measured | Low | P4 | self | R-984 |
|
||||
| SR-18 | promise | Zero-knowledge wording is stronger than a live box allows | static | Medium | P3 | self | R-985 (decision) |
|
||||
| SR-19 | process | No scanner on any push; catalog images never scanned | measured | Medium | P3/P4 | self | R-986, R-987 |
|
||||
| SR-20 | hub | The exposure window cannot be seen in the logs | measured | — | P2 | self | R-954 (decision) |
|
||||
| SR-21 | process | A gate test writes into the real repo when pushed from a worktree | measured | Low | — | self | note on R-935 |
|
||||
| SR-22 | hub | Nothing fails when a new hub route has no login decision | static | Medium | P3 | — | R-952 |
|
||||
| SR-23 | hub | A full ArgoCD sync with prune would delete three live Secrets | measured | Medium | P3 | — | R-953 |
|
||||
| SR-24 | hub | Cross-box check: holds in source and tests; not fully proven | static + tests | — | P4 | — | R-955 |
|
||||
|
||||
**SR-01 (closed).** The key was rotated on 2026-10-12 with the operator's go; the old value now gets 403/401.
|
||||
Whether it was used before is SR-20.
|
||||
**SR-02 (closed).** Hub 0.148.0: operator key only; test plus red-proof; live check in `evidence/hub-0.148.0-live-check.txt`.
|
||||
**SR-03 – SR-05.** Open Highs; see the next-task list.
|
||||
|
||||
## Next tasks, ranked
|
||||
|
||||
1. **R-954 — the operator decides about the box root passwords** (the exposure window is not visible in the logs).
|
||||
2. **R-970 — remove the box's settings-file route** (nothing calls it), with a test that it is gone.
|
||||
3. **R-972 — rebuild the controller, hub and agent on a supported, patched Go**, update x/crypto, refresh the base
|
||||
images. Today Go 1.27 and 1.26 are supported; the shipped controller and hub use 1.24.13 (unsupported) and the agent
|
||||
1.26.0 (supported line, missing nine patch releases). Source: the Go release policy and the scanner output above.
|
||||
4. **R-971 — the operator decides on the catalog privilege check; then build the box-side check.**
|
||||
5. **R-952 — the hub route guard test.**
|
||||
6. **R-953 — stop ArgoCD from wanting to prune the three live Secrets.**
|
||||
7. Then the Medium rows in order: R-973, R-974, R-975, R-976, R-977, R-978, R-979, R-980, R-981, R-982, R-985.
|
||||
Reference in New Issue
Block a user