Files
felhom.eu/documentation/audits/security-review-2026-10-12/SCANNERS.md
T

6.5 KiB
Raw Blame History

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 <file> 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 <repo> --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 <image> (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.