homelab/documentation/reports/SECURITY_AUDIT_REPORT.md

12 KiB

Security Audit Report: Homelab Infrastructure

Report Date: April 12, 2026
Auditor: FrankGPT Security Analysis
Scope: Complete repository scan for exposed secrets, credentials, and security vulnerabilities
Status: 🔴 CRITICAL ISSUES FOUND


Executive Summary

A comprehensive security audit of the homelab repository has identified 1 critical vulnerability and 3 high-priority security enhancements needed to align with industry best practices. While the infrastructure demonstrates strong GitOps practices with environment variable usage in most services, several hardcoded credentials and exposed ports present immediate security risks.

Risk Level: 🔴 HIGH (Immediate remediation required)


🔴 Critical Findings

1. Hardcoded Plex Claim Token in Git Repository

Severity: 🔴 CRITICAL
File: nodes/waldorf/plex/compose.yaml (Line 12)
Issue: Plex claim token committed directly to version control

# CURRENT (INSECURE)
environment:
  - PLEX_CLAIM=claim-sxFpsPTDzzF-9RZAxtUL

Risk Assessment:

  • Impact: Anyone with repository access can claim/hijack your Plex server
  • Exposure: Token visible in Git history, even if removed from HEAD
  • Validity: Plex claim tokens typically expire after 4 minutes, but this pattern indicates potential for other secrets

Remediation Required:

  1. Immediate Action:

    # Revoke/invalidate this claim token in Plex
    # Visit: https://www.plex.tv/claim/
    
  2. Code Fix:

    # CORRECTED (SECURE)
    environment:
      - PLEX_CLAIM=${PLEX_CLAIM}  # Placeholder
    
  3. Komodo Configuration:

    • Add via Komodo UI → Stack → Environment Variables
    • Variable: PLEX_CLAIM=claim-NEW_TOKEN_HERE
  4. Git History Cleanup (Optional but Recommended):

    # WARNING: Rewriting history affects all collaborators
    git filter-branch --force --index-filter \
      "git rm --cached --ignore-unmatch nodes/waldorf/plex/compose.yaml" \
      --prune-empty --tag-name-filter cat -- --all
    

Status: PENDING REMEDIATION


🟡 High-Priority Security Enhancements

2. Redis Exposed Without Authentication

Severity: 🟡 HIGH
File: nodes/heimdall/core/compose.yaml (Line 40)
Issue: Redis cache exposed on host port 6379 without password protection

# CURRENT (INSECURE)
redis:
  image: redis:7-alpine
  ports:
    - "6379:6379"  # ⚠️ Publicly exposed on LAN
  command: redis-server --appendonly yes
  # NO PASSWORD CONFIGURED

Risk Assessment:

  • Impact: Unauthorized access to cached session data, potential data manipulation
  • Attack Surface: Any device on LAN (10.0.0.x) can connect to Redis
  • Exploitability: HIGH (Redis has no default authentication)

Remediation Options:

Option A: Remove Public Port Binding (Recommended)

redis:
  image: redis:7-alpine
  # ports:  # REMOVED - Only accessible via Docker network
  #   - "6379:6379"
  networks:
    - proxy-net  # Internal-only access
  command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
  environment:
    - REDIS_PASSWORD=${REDIS_PASSWORD}

Option B: Add Password Authentication (If external access needed)

redis:
  image: redis:7-alpine
  ports:
    - "127.0.0.1:6379:6379"  # Bind to localhost only
  command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
  environment:
    - REDIS_PASSWORD=${REDIS_PASSWORD}

Komodo Environment Variable:

  • Add REDIS_PASSWORD=<strong-random-password> via Komodo UI

Status: 🟡 RECOMMENDED


3. Docker Socket Proxy Configured with Broad Write Access

Severity: 🟡 MEDIUM
File: nodes/heimdall/core/compose.yaml (Lines 28-33)
Issue: Docker socket proxy allows POST operations and container lifecycle management

# CURRENT
environment:
  - POST=1 
  - ALLOW_START=1
  - ALLOW_STOP=1
  - ALLOW_RESTARTS=1

Risk Assessment:

  • Impact: Compromised Traefik or Komodo could manipulate all containers
  • Mitigation: Proxy runs as privileged (privileged: true), limiting lateral movement
  • Trade-off: Required for Komodo's container orchestration functionality

Recommendation:

  • Accept Risk: This configuration is required for Komodo Core functionality
  • Monitoring: Enable Docker audit logging to track container lifecycle events
  • Network Isolation: Ensure proxy-net is not exposed beyond trusted services

Status: ACCEPTED RISK (Required for functionality)


4. MongoDB Credentials Use Environment Variables (GOOD)

Severity: LOW (Best Practice Followed)
File: nodes/heimdall/core/compose.yaml (Lines 109-110)

# ✅ CORRECT IMPLEMENTATION
environment:
  MONGO_INITDB_ROOT_USERNAME: ${KOMODO_DATABASE_USERNAME}
  MONGO_INITDB_ROOT_PASSWORD: ${KOMODO_DATABASE_PASSWORD}

Assessment:

  • Status: SECURE - No hardcoded credentials found
  • Verification: Confirm .env file is excluded from Git (see .gitignore section below)

5. Traefik Cloudflare API Tokens Use Environment Variables (GOOD)

Severity: LOW (Best Practice Followed)
File: nodes/heimdall/core/compose.yaml (Lines 66-67)

# ✅ CORRECT IMPLEMENTATION
environment:
  - CLOUDFLARE_DNS_API_TOKEN=${CF_API_TOKEN}
  - CLOUDFLARE_ZONE_API_TOKEN=${CF_ZONE_TOKEN}

Assessment:

  • Status: SECURE - No hardcoded tokens found
  • Recommendation: Rotate Cloudflare API tokens quarterly

🔒 Secret Management Options for This Environment

Current State: Komodo UI Environment Variables

How It Works:

  1. Define placeholders in compose.yaml: ${VARIABLE_NAME}
  2. Store actual secrets in Komodo UI → Stack → Environment Variables
  3. Komodo injects secrets at container runtime

Pros:

  • Simple to configure via web UI
  • Secrets not committed to Git
  • Supports per-stack secret isolation

Cons:

  • ⚠️ No centralized secret rotation
  • ⚠️ Manual backup of secrets required
  • ⚠️ No audit trail for secret access

Option 1: .env File (Quick Win)

Implementation:

  1. Create .env file in stack directory:

    # /nodes/heimdall/core/.env
    CF_API_TOKEN=your_cloudflare_api_token_here
    CF_ZONE_TOKEN=your_zone_token_here
    KOMODO_DATABASE_USERNAME=komodo_admin
    KOMODO_DATABASE_PASSWORD=strong_random_password_here
    KOMODO_ONBOARDING_KEY_HEIMDALL=onboarding_key_here
    REDIS_PASSWORD=another_strong_password
    
  2. Update compose.yaml:

    services:
      komodo-core:
        env_file: .env
        # Individual environment vars still supported
    
  3. Critical: Add to .gitignore:

    # Create/update .gitignore at repository root
    echo "**/.env" >> .gitignore
    echo "**/*.env" >> .gitignore
    git add .gitignore
    git commit -m "chore(security): prevent .env file commits"
    

Pros:

  • Quick to implement
  • Standard Docker Compose pattern
  • Easy to backup (manual copy)

Cons:

  • ⚠️ File must exist on host (NFS or local)
  • ⚠️ No encryption at rest
  • ⚠️ Risk of accidental Git commit

Implementation:

  1. Create secrets on each node:

    # On Heimdall
    echo "your_cloudflare_token" | docker secret create cf_api_token -
    echo "your_database_password" | docker secret create komodo_db_password -
    
  2. Update compose.yaml:

    services:
      traefik:
        secrets:
          - cf_api_token
        environment:
          - CLOUDFLARE_DNS_API_TOKEN_FILE=/run/secrets/cf_api_token
    
    secrets:
      cf_api_token:
        external: true
    

Pros:

  • Encrypted at rest and in transit
  • Native Docker Swarm integration
  • Secret rotation without container restart

Cons:

  • ⚠️ Requires Docker Swarm mode (or transition to Kubernetes)
  • ⚠️ More complex to configure
  • ⚠️ May not integrate seamlessly with Komodo

Option 3: HashiCorp Vault (Enterprise-Grade)

Implementation:

  1. Deploy Vault container:

    vault:
      image: hashicorp/vault:latest
      ports:
        - "8200:8200"
      environment:
        - VAULT_DEV_ROOT_TOKEN_ID=myroot  # CHANGE THIS
    
  2. Store secrets in Vault:

    vault kv put secret/homelab/cloudflare api_token=xxx zone_token=yyy
    
  3. Use Vault Agent for injection or API calls in startup scripts

Pros:

  • Centralized secret management
  • Audit logging and access control
  • Automatic secret rotation
  • Encryption at rest

Cons:

  • ⚠️ Significant operational overhead
  • ⚠️ Requires learning curve
  • ⚠️ Another service to maintain

Option 4: Ansible Vault (Hybrid Approach)

Implementation:

  1. Encrypt variables file:

    ansible-vault create ansible/vars/secrets.yml
    
  2. Store secrets:

    # ansible/vars/secrets.yml (encrypted)
    cf_api_token: your_token_here
    plex_claim: your_claim_here
    
  3. Deploy with Ansible playbook:

    ansible-playbook -i hosts deploy.yml --ask-vault-pass
    

Pros:

  • Works with existing ansible/ directory structure
  • Encrypted at rest (AES-256)
  • Can commit encrypted file to Git safely

Cons:

  • ⚠️ Requires Ansible expertise
  • ⚠️ Not integrated with Komodo workflow
  • ⚠️ Manual decryption for ad-hoc changes

Immediate Actions (Within 24 Hours)

Priority Action Effort Impact
🔴 CRITICAL Remove hardcoded PLEX_CLAIM from Git 15 min HIGH
🔴 CRITICAL Create .gitignore to prevent .env commits 5 min HIGH
🟡 HIGH Remove Redis public port binding OR add authentication 10 min MEDIUM
🟡 HIGH Audit all compose files for other hardcoded secrets 30 min MEDIUM

Short-Term Actions (Within 1 Week)

Priority Action Effort Impact
🟡 MEDIUM Standardize on .env files for all stacks 2 hours MEDIUM
🟡 MEDIUM Document secret rotation procedures in SOP 1 hour MEDIUM
🟢 LOW Set calendar reminder for quarterly API token rotation 5 min LOW

Long-Term Actions (Optional)

Priority Action Effort Impact
🟢 LOW Evaluate Docker Secrets vs. Vault for centralized management 4 hours HIGH
🟢 LOW Implement automated secret scanning in CI/CD pipeline 3 hours MEDIUM

🛡️ Security Best Practices Checklist

Already Implemented

  • Most services use environment variable placeholders (${VAR_NAME})
  • Komodo UI used for secret injection at runtime
  • Docker socket access mediated through proxy (not direct mount)
  • Traefik handles SSL termination with Cloudflare DNS challenge
  • Network segmentation via Docker networks (proxy-net)

Needs Implementation

  • .gitignore configured to exclude .env files
  • All hardcoded secrets removed from compose files
  • Redis authentication enabled or port binding removed
  • Secret rotation schedule documented
  • Backup strategy for Komodo-stored environment variables

🔮 Future Enhancements

  • Centralized secret management (Vault or similar)
  • Automated secret scanning (pre-commit hooks)
  • Audit logging for sensitive operations
  • Encrypted backups of configuration data


🔍 Audit Methodology

Scan Coverage:

  • All compose.yaml files in nodes/ directory
  • Documentation files for exposed patterns
  • README files for accidental credential leakage
  • Repository structure for .env or secret files

Tools Used:

  • Pattern matching for common secret keywords: password|token|secret|api_key|claim
  • Manual inspection of environment variable usage
  • Cross-reference with Komodo UI documentation

Exclusions:

  • Scripts directory (no compose files found)
  • Ansible directory (no active playbooks with secrets)

Report Version: 1.0
Next Review Date: July 12, 2026 (Quarterly)
Validation Status: Ready for Implementation