Skip to content

Security & Vulnerability Gaps

Known security findings, mitigations in place, and areas for improvement. Cross-references the full audit in homelab-notes/deep-dive.md.


Active Findings

SG-001 — qBittorrent CSRF bypass required for reverse proxy

Status: Mitigated Affected services: seedbox.eva-00.network, normal.eva-00.network Date identified: 2026-03-30

Issue: qBittorrent 5.x CSRF protection fires before AuthSubnetWhitelist evaluation. When oauth2-proxy forwards authenticated requests, the Origin/Referer headers don't match what qBittorrent expects, causing a 401 even though the client IP is whitelisted.

Mitigation: CSRFProtection, ClickjackingProtection, and HostHeaderValidation are disabled in qBittorrent's config. These checks are redundant because:

  • All external access goes through oauth2-proxy (PocketID SSO) on LXC 119 (infra-apps)
  • AuthSubnetWhitelist=192.168.1.118/32, 192.168.1.119/32 restricts unauthenticated access to qbitwebui (LXC 118) and oauth2-proxy (LXC 119) only
  • No qBittorrent ports are exposed to the internet

Residual risk: Low. Only processes on LXC 118 (tools) and LXC 119 (infra-apps) can reach qBittorrent without auth. These are dedicated single-purpose LXCs with limited attack surface.

References: - services/seedbox/fix-webui-auth.py — the script that applies all settings - docs/services/pocketid/oauth2-proxy-integration.md — step 7 documents the bypass - deep-dive.md Section 2 — Security Best Practices — general reverse proxy security guidance


SG-002 — qbitwebui API exposed on localhost without authentication

Status: Accepted Affected services: qbit.eva-00.network Date identified: 2026-03-30

Issue: qbitwebui runs with DISABLE_AUTH=true on LXC 118 (tools). The API allows listing, adding, and deleting qBittorrent instances without credentials.

Mitigation: External access goes through oauth2-proxy on LXC 119 (PocketID SSO required). The qbitwebui port is only reachable from the LAN.

Residual risk: Low. Shell access to LXC 118 is the prerequisite. Instance credentials are AES-256-GCM encrypted in the SQLite database, but the encryption key is in the .env file on the same host.


SG-003 — Flat network — no segmentation

Status: Open Affected services: All Date identified: 2026-03-24

Issue: All LXCs and the Proxmox host share a single subnet (192.168.1.0/24). Any compromised container can reach any other service directly.

Impact: A compromised service (e.g., a vulnerable web app) could scan and attack other services on the same subnet, access Vault directly, or pivot to Proxmox.

Recommendation: Implement VLAN segmentation. Start with isolating Vault (high-value target) and internet-facing LXCs onto separate VLANs with firewall rules.

Reference: deep-dive.md Section 7 — Network Hardening — full VLAN strategy and zero-trust options


SG-004 — No intrusion detection/prevention

Status: Open Affected services: All internet-facing services Date identified: 2026-03-24

Issue: No IDS/IPS is deployed. Brute force attacks on oauth2-proxy, PocketID, or SSH are not detected or blocked. Caddy serves requests without rate limiting.

Recommendation: Deploy CrowdSec with the Caddy bouncer module. This provides community-shared blocklists, brute force detection, and automated blocking.

Reference: deep-dive.md Section 11 — CrowdSec + Caddy Implementation Guide


SG-005 — No security headers on Caddy

Status: Open Affected services: All .eva-00.network Date identified:* 2026-03-24

Issue: Caddy does not set security headers (HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy). This leaves services vulnerable to clickjacking, MIME sniffing, and other browser-based attacks.

Recommendation: Add a global (security_headers) snippet to the Caddyfile.

Reference: deep-dive.md Section 7.2 — Caddy Security Headers — exact Caddyfile config provided


SG-006 — Hardcoded LXC password in playbooks

Status: Open Affected services: vault.yml, filedump.yml Date identified: 2026-03-24

Issue: LXC creation uses --password bigboydata, exposed in Git history. SSH key-only access is configured, so the password is a secondary risk, but it's still a bad practice.

Recommendation: Generate a random password at creation time and discard it. SSH keys are already the primary access method.

Reference: deep-dive.md Section 1.1 — Hardcoded LXC Password


SG-007 — Shell/JSON injection in Ansible playbooks

Status: Open Affected services: forgejo.yml, n8n.yml Date identified: 2026-03-24

Issue: Vault secrets injected into shell commands and JSON strings without escaping. A secret containing ', ", or \ could break or inject commands.

Recommendation: Use | quote for shell variables and | to_json for JSON embedding.

Reference: deep-dive.md Sections 1.2, 1.3, 1.4 — specific file paths and fix patterns


SG-008 — No Vault audit logging

Status: Open Affected services: Vault (LXC 106) Date identified: 2026-03-24

Issue: Vault does not have audit logging enabled. There is no record of who accessed which secret, when. If credentials are leaked, there is no trail to investigate.

Recommendation: Enable Vault's file audit device and ship logs to Loki via Alloy.

Reference: deep-dive.md Section 2.7 — Audit Logging


SG-009 — Containers run as root

Status: Open Affected services: Most Docker services across all LXCs Date identified: 2026-03-24

Issue: Most containers run as root inside the container. A container escape vulnerability could grant root access to the Docker host.

Recommendation: Add user: "1000:1000" and security_opt: [no-new-privileges:true] where the service supports it. Apply incrementally — not all services support non-root.

Reference: deep-dive.md Section 2.3 — Container Security Hardening


SG-010 — No image vulnerability scanning

Status: Open Affected services: All Docker services Date identified: 2026-03-24

Issue: Docker images are pulled and deployed without CVE scanning. A compromised or vulnerable upstream image could introduce exploits.

Recommendation: Add Trivy scanning to deploy workflows. Fail on HIGH/CRITICAL CVEs.

Reference: deep-dive.md Section 2.4 — Vulnerability Scanning


Closed Findings

SG-C01 — qBittorrent auth bypass was 0.0.0.0/0

Status: Fixed (2026-03-30)

Issue: fix-webui-auth.py set AuthSubnetWhitelist=0.0.0.0/0, disabling auth for all IPs. Any device on the LAN (or anything that could route to LXC 111) had full unauthenticated access to qBittorrent.

Fix: Tightened to 192.168.1.118/32, 192.168.1.119/32 (qbitwebui + oauth2-proxy only). Combined with CSRF/clickjacking/host-validation disables (SG-001) to maintain reverse proxy compatibility.