# REPORT — security review 2026-10-12, parts 1 and 2 Written as `REPORT-.md`, not `REPORT.md`: other sessions worked in this repository at the same time (`CLAUDE.md`, „two sessions clobber each other"). ## In plain language - **Is the hub closed now? Yes.** The old master key is dead (rotated with your yes). The open customer page needs the master key since hub 0.148.0, which is live and checked. - **Did anyone use the holes? Cannot tell.** The logs cover only 2026-10-12 from about 09:54, and one day in June. The holes were open since February 2026 — about **238 days** that no log shows. - **You must decide four things** (`STATUS.md`, D1–D4): change every box's root password (my pick: yes); a box-side check on catalog changes (my pick: yes); the zero-knowledge wording (my pick: change it now); root password SSH from the LAN (my pick: key only). - **Next tasks, in order:** R-954 (your decision) → R-970 (remove the box's settings-file route) → R-972 (patched Go and base images) → R-971 (catalog check) → R-952 (hub route guard test) → R-953 (ArgoCD prune danger) → the medium rows. ## What did not go as written - **The safety filter stopped this session three times** — while writing the first findings table, the hub route-guard test (Scenario D), and the Part 2 log search. As the operator ruled, each became short register rows: R-952 (route guard), R-954 (the log question). The detailed working notes are off-git: `/mnt/5_hdd/felhom.eu/evidence/security-review-2026-10-12-PRIVATE/`. - **The live cross-box GETs (Part 3) were not run.** The source and unit tests answer the question; the live check is in R-955. - **One red-proof, not five,** for the new cross-box tests (R-955). - **A gate test wrote into the shared repository** when this session pushed from a git worktree: four test commits in the worktree and `user.name d` in the shared `.git/config` (two other-session commits carry that author). The session removed the `[user]` section, stopped pushing from the worktree, and pushed from a normal clone instead. Noted on R-935 (the `core.bare` flips another session filed). - **Register ids R-934/R-935 collided with another session;** this session's rows moved to R-950–R-955 and R-970–R-987. ## Baselines felhom.eu `0d463a85` at the start of part 2 (hub 0.147.0 live, no unreleased hub code after its release commit `655f5f66`); controller `dcd89364a4`; agent `86adbcaf8a`. ArgoCD: the hub was Synced; three Secrets and `Deployment/umami` OutOfSync (R-953). ## Release — hub v0.148.0 - Commits: `b67b8cea` (code), `8d34d607` (manifest). Built from a clean clone at `b67b8cea` (the shared clone held another session's unpushed commit, so the build script's own pull could not run; the script was used unchanged except for the source folder). - ArgoCD: a sync of `Deployment/hub` only, no prune; operation Succeeded at `8d34d607`. Image `gitea.dooplex.hu/admin/felhom-hub:0.148.0`, pod Ready. The three Secrets are still present. - Live check (`audits/security-review-2026-10-12/evidence/hub-0.148.0-live-check.txt`): no credential → 403 on all three routes, no customer in the body; the master key → 200. - All three boxes reported after the restart (controller and agent reports), 0 auth failures in the hub log. ## Tests - `TestCustomersRoutes_NoCredentialIsRefused`, `…_BoxKeysAreRefused`, `…_GlobalKeyUnchanged` — pass. **Red-proof:** with the check removed from `handleCustomer`, the first failed (`GET /customers/c1` answered 200). - Five cross-box tests (`crossbox_refusal_test.go`) — pass. Red-proof on the restore-directive test: with its host check disabled it failed (another box's key got 200). The first try was masked by a later check; the test now arms recovery mode so only the host check can refuse. - Hub test functions: 1079 before → 1087 after. Green gate: `go build`, `go vet`, `go test ./...` in `hub/` pass. ## Part 2 — logs | log | oldest line it holds | |---|---| | ingress-nginx controller, rotated files on DooPlex | one file 2026-06-10 08:08–16:44; then 2026-10-12 09:54 onward | | hub pod log | only the current pod (2026-10-12 ~16:57 onward); older pods' logs are gone | | central log store | none exists on DooPlex | | Cloudflare | none: hub.felhom.eu is not proxied by Cloudflare | The search for strange addresses was not completed (see above). Blind window: from 2026-02-16 (the key's first commit) to 2026-10-12 09:54 — about 238 days. FILED: R-954. ## Register Rows before this part: 97. After: 119. Opened: 22 open (R-952–R-955, R-970–R-987) plus 2 born closed (R-950, R-951, in `CLOSED-ITEMS.md`). Closed: 2. Noted: R-935, R-132, R-908. (Other sessions also changed the register today; these numbers count this session's rows.) ## Observations - Hub key exposure — FILED: R-950 (closed, rotated). - Open customer routes — FILED: R-951 (closed, hub 0.148.0). - Route guard missing — FILED: R-952. - ArgoCD would prune live Secrets — FILED: R-953. - Exposure window not visible — FILED: R-954. - Cross-box check not fully proven — FILED: R-955. - Part 1 findings — FILED: R-970 to R-987 (see `FINDINGS.md`). - Gate test writes into the real repo from a worktree — NOT-A-FINDING here: a note on R-935, which owns it. - Hub login hash in the public manifest — NOT-A-FINDING here: a note on R-132. - gitleaks misses R-908's key — NOT-A-FINDING here: a note on R-908 and input to R-986. - Old registry token and old Resend key in history — NOT-A-FINDING: both rotated (checked by hash / last eight characters). - System poster: no fact in `felhom-system-poster.facts.md` changed. ## Teardown Machines: nothing provisioned; demo-hp was only read. Host: none. Hub: one release (0.148.0) and the key rotation; no other change. DooPlex files: the private evidence folder, the scanner tools under `/mnt/5_hdd/felhom.eu/tools/security/`, the git worktree and clone under `/mnt/5_hdd/felhom.eu/wt/`, and a copy of the build script (`build/felhom-hub/build-0.148.0-from-clean-clone.sh`).