# Scanner baseline — security review 2026-10-12 Standard (non-AI) tools, installed as user binaries under `/mnt/5_hdd/felhom.eu/tools/security/bin/` on DooPlex. Nothing was installed system-wide or on any box. Raw output (redacted) is in `scanners/`. | tool | version | how installed | sha256 of the binary (first..last 4) | |---|---|---|---| | govulncheck | v1.1.4 | `go install golang.org/x/vuln/cmd/govulncheck@v1.1.4` | 6b04..2f5e | | gosec | v2.22.4 | `go install github.com/securego/gosec/v2/cmd/gosec@v2.22.4` | 3111..607e | | gitleaks | 8.24.3 | GitHub release tarball, checked against the release checksums file | e183..72d3 | | trivy | 0.74.0 | GitHub release tarball, checked against the release checksums file | d89b..d7b9 | Trivy note: releases 0.27–0.69.1 are no longer published upstream; 0.74.0 (2026-08-14) was the newest release older than two weeks. ## Reviewed commits controller `dcd89364a4` (v0.307.0) · agent `86adbcaf8a` (v0.154.0) · felhom.eu `c9b9432986` · catalog `1a642b43e7` · homelab-manifests `fdd324bb62`. Shipped artifacts: controller image `0.307.0`, hub image `0.146.0`, agent binary `0.154.0` (copied from demo-hp). ## 1. govulncheck Commands: `govulncheck ./...` in each module (source mode), and `govulncheck -mode binary ` on the shipped binaries. Source mode reports the stdlib of the LOCAL toolchain (go1.26.0), not the one that built the shipped program, so the binary mode is the one that counts. | target | built with | vulnerabilities reported as reachable | triage | |---|---|---|---| | controller 0.307.0 binary | go1.24.13, x/crypto v0.31.0 | 62 (stdlib + x/crypto/ssh) | real → R-972 (toolchain) | | hub 0.146.0 binary | go1.24.13, x/crypto v0.31.0 | 62 (stdlib + x/crypto/ssh) | real → R-972 | | agent 0.154.0 binary | go1.26.0 | 27 (stdlib) | real → R-972 | | source mode, three modules | local go1.26.0 | 46 / 45 / 27 | superseded by the binary rows | Mostly denial-of-service fixes; it includes html/template escaping fixes and x/crypto/ssh fixes. Go 1.24 is past the Go support window (the two newest major releases: https://go.dev/doc/devel/release#policy). ## 2. gitleaks Command: `gitleaks git --redact=100 --log-opts=--all -f json`, full history of all five repositories. Redacted reports in `scanners/` (author name and e-mail dropped). Each hit was triaged by masked context only: the line was shown with every long token replaced by its length and a hash prefix; no value was printed. | repo | hits | triage | |---|---|---| | felhom-controller | 12 | 4 were one live credential → R-950 (rotated 2026-10-12; withheld from the report file); the rest are test constants, docs and decoy fixtures | | felhom-agent | 15 | all test fixtures | | felhom.eu | 43 | 1 → R-950 (withheld); 5 are `manifests/felhom.secret.yaml` history → R-925; the rest are old evidence logs of throwaway demo apps (values compared by hash with the running demo apps: none match), test constants, public keys, fingerprints | | app-catalog-felhom.eu | 1 | a health-probe URL, noise | | homelab-manifests | 17 | private repository; locations kept off-git; not product. gitleaks did NOT flag R-908's key (note on R-908) | A credential found only in history counted until its rotation was checked: the old Gitea registry token in felhom.eu history is not among the admin account's live tokens (compared by its last eight characters with the token list); the old Resend key in hub.yaml history was rotated in June (hash differs from the live one). ## 3. trivy image Command: `trivy image --image-src remote --scanners vuln -f json ` (registry API, no Docker daemon). | image | OS | fixable CRITICAL / HIGH (OS) | Go binary | triage | |---|---|---|---|---| | felhom-controller:0.307.0 | Debian 12.15 | 12 / 23 | felhom-controller go1.24.13 (34 HIGH) | real → R-972 | | felhom-hub:0.146.0 | Alpine 3.21.8 | 0 / 2 | felhom-hub go1.24.13 (34 HIGH) | real → R-972 | | felhom-samba:1.1.0 | Alpine 3.21.7 | 0 / 48 | — | real → R-972 | | traefik:v3.7.13 | Alpine 3.24.2 | 0 / 0 | 4 HIGH (upstream) | upstream; R-979 (pins) | | cloudflared:2026.9.3 | Debian 13.7 | 0 / 1 | 4 HIGH (upstream) | upstream | | filebrowser 1.5.6-stable | Alpine 3.24.1 | 1 / 2 | 4 HIGH (upstream) | upstream | Not scanned: the 53 catalog app images → R-987. ## 4. gosec (leads only) Command: `gosec -quiet -tests=false -fmt=json ./...` per module. Hits: controller 470, agent 117, hub 215. Triage of the high-signal rules: G202 (SQL string building) — every hit builds `?` placeholders, noise. G402 (TLS verify off) — each sits beside a certificate pin, noise. G407/G404 — the export cipher uses random IVs and scrypt, a backoff jitter uses math/rand, noise. G101 — comments and constant names, noise. G304/G301/G306/G104 — bulk noise, not filed. ## 5. The push gate (R-986, wired 2026-10-19) `scripts/security_scan_gate.py` (shared by the four repos, in each runner's FAST set and in CI), **warn-first**: it lists hits and exits 0. govulncheck (called vulnerabilities only) on each Go module; gitleaks on the commits being pushed; accepted hits per repo in `.security-accepted` (gitleaks by rule + a hash of the hit's line + file, so one accepted test constant does not accept the next secret in the same file). First scan of every repo's `main` with verdicts: `documentation/audits/night-2026-10-19/P7/triage.md` (0 real secrets, 0 called vulnerabilities). | tool | version | how installed | sha256 | |---|---|---|---| | govulncheck | **v1.8.0** (2026-09-08), built with go1.27.2 | `GOTOOLCHAIN=go1.27.2 go install golang.org/x/vuln/cmd/govulncheck@v1.8.0` → `tools/security/bin/govulncheck-v1.8.0` (`govulncheck` links to it) | `aec435d4c0b29cb8987d466ae61ed4c334eab7d4b58073aaa873702c50a0da02` | | gitleaks | 8.24.3 (unchanged) | the same binary; CI fetches the release tarball | tarball `9991e0b2903da4c8f6122b5c3186448b927a5da4deef1fe45271c3793f4ee29c` (the release's own checksums file), binary `e18325d5…69ad` | **Why the govulncheck pin moved:** v1.1.4 (the 2026-10-12 pin) cannot read the repos since they moved to Go 1.27.2: built with go1.26 it fails to load the standard library (`unknown field rfd in struct literal of type splicePipe`), and rebuilt with go1.27.2 it panics in its SSA builder (`unexpected expr: *ast.KeyValueExpr`). v1.8.0 is the newest release older than two weeks (v1.9.0 is from 2026-10-11). The old binary is kept as `govulncheck-v1.1.4-go1.26.0`. **CI:** the runner has python3 and git and no Go, so govulncheck says NOT CHECKED there, out loud; the pre-push hook (with Go) runs it. gitleaks is fetched pinned (`FELHOM_SCAN_FETCH=1` in each `gates.yml`), both checksums checked.