Files
media-downloader/docs/archive/SECURITY_AUDIT_2025-10-31.md
Todd 0d7b2b1aab Initial commit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 22:42:55 -04:00

10 KiB

Security Audit Report

Date: 2025-10-31 Application: Media Downloader v6.3.3 Auditor: Claude Code Severity Levels: 🔴 Critical | 🟠 High | 🟡 Medium | 🟢 Low


Executive Summary

A comprehensive security audit was conducted on the Media Downloader application. 6 critical vulnerabilities were identified that require immediate attention. The application has good foundations (bcrypt, JWT, rate limiting) but lacks proper authentication enforcement and network security.

Risk Level: 🔴 CRITICAL


Critical Vulnerabilities (Immediate Action Required)

🔴 1. NO FIREWALL ENABLED

Severity: CRITICAL Impact: All services exposed to network

Finding:

$ sudo ufw status
Status: inactive

Exposed Services:

  • Port 8000: FastAPI backend (0.0.0.0 - all interfaces)
  • Port 5173: Vite dev server (0.0.0.0 - all interfaces)
  • Port 3456: Node service (0.0.0.0 - all interfaces)
  • Port 80: Nginx

Risk:

  • Anyone on your network (192.168.1.0/24) can access these services
  • If port-forwarded, services are exposed to the entire internet
  • No protection against port scans or automated attacks

Fix (URGENT - 15 minutes):

# Enable firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH (if remote)
sudo ufw allow 22/tcp

# Allow only nginx (reverse proxy)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Block direct access to backend ports
# (nginx should proxy to localhost:8000)

# Enable firewall
sudo ufw enable

🔴 2. 95% OF API ENDPOINTS ARE UNAUTHENTICATED

Severity: CRITICAL Impact: Anyone can access/modify your data

Finding:

  • Total endpoints: 43
  • Authenticated: 2 (4.6%)
  • Public (no auth): 41 (95.4%)

Unauthenticated Endpoints Include:

  • /api/downloads - View ALL downloads
  • /api/downloads/{id} - DELETE downloads
  • /api/platforms/{platform}/trigger - Trigger downloads
  • /api/scheduler/current-activity/stop - Stop downloads
  • /api/scheduler/tasks/{task_id}/skip - Modify schedule
  • /api/config - View/modify configuration
  • /api/media/* - Access all media files

Risk:

  • Anyone on your network can:
    • View all your downloads
    • Delete your files
    • Trigger new downloads
    • Stop running downloads
    • Modify configuration
    • Access your media library

Fix (HIGH PRIORITY - 2 hours): Add Depends(get_current_user) to all sensitive endpoints:

# BEFORE (VULNERABLE)
@app.delete("/api/downloads/{download_id}")
async def delete_download(download_id: int):

# AFTER (SECURE)
@app.delete("/api/downloads/{download_id}")
async def delete_download(
    download_id: int,
    current_user: Dict = Depends(get_current_user)  # ADD THIS
):

🔴 3. DATABASES ARE WORLD-READABLE

Severity: CRITICAL Impact: Sensitive data exposure

Finding:

-rw-r--r-- root root /opt/media-downloader/database/auth.db
-rw-r--r-- root root /opt/media-downloader/database/media_downloader.db

Risk:

  • Any user on the system can read:
    • Password hashes (auth.db)
    • User sessions and tokens
    • Download history
    • All metadata

Fix (5 minutes):

# Restrict database permissions
sudo chmod 600 /opt/media-downloader/database/*.db
sudo chown root:root /opt/media-downloader/database/*.db

# Verify
ls -la /opt/media-downloader/database/*.db
# Should show: -rw------- root root

🔴 4. DEVELOPMENT SERVERS RUNNING IN PRODUCTION

Severity: HIGH Impact: Performance, stability, security

Finding:

  • Vite dev server on port 5173 (should be built static files)
  • Development mode has verbose errors, source maps, hot reload
  • Not optimized for production

Risk:

  • Exposes source code and stack traces
  • Poor performance
  • Memory leaks
  • Not designed for production load

Fix (30 minutes):

# Build production frontend
cd /opt/media-downloader/web/frontend
npm run build

# Serve via nginx, not Vite dev server
# Update nginx config to serve dist/ folder

# Stop Vite dev server
sudo systemctl stop vite-dev-server  # (if running as service)

🔴 5. NO RATE LIMITING ON API

Severity: HIGH Impact: Denial of Service, brute force attacks

Finding:

  • No rate limiting middleware on FastAPI
  • Login endpoint has application-level rate limiting (good)
  • But other endpoints have no protection

Risk:

  • API can be flooded with requests
  • Download all your files via API spam
  • Trigger hundreds of downloads simultaneously
  • DDoS the service

Fix (2 hours): Install slowapi:

from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded

limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

# Apply to routes
@app.get("/api/downloads")
@limiter.limit("10/minute")  # 10 requests per minute
async def get_downloads(...):

Severity: MEDIUM Impact: Session hijacking potential

Finding:

-rw-r--r--  1 root root 1140 fastdl_cookies.json   # World-readable
-rw-------  1 root root  902 forum_cookies.json    # Secure
-rw-rw-r--  1 root root 4084 toolzu_cookies.json   # Group-writable

Risk:

  • Other users/processes can steal cookies
  • Session hijacking across platforms

Fix (2 minutes):

sudo chmod 600 /opt/media-downloader/cookies/*.json
sudo chown root:root /opt/media-downloader/cookies/*.json

Additional Security Concerns

🟡 7. CORS Configuration (Development Only)

Current:

allow_origins=["http://localhost:5173", "http://localhost:3000"]

Issue: If accessed via IP or domain name, CORS will block. Need production config.

Fix:

# Production
allow_origins=["https://yourdomain.com"]

# Or if same-origin (nginx proxy)
# No CORS needed

🟡 8. JWT Secret Key

Current:

SECRET_KEY = os.environ.get("JWT_SECRET_KEY", secrets.token_urlsafe(32))

Issue:

  • Falls back to random key on each restart
  • Invalidates all sessions on restart
  • Not persisted

Fix:

# Generate and save secret
echo "JWT_SECRET_KEY=$(openssl rand -hex 32)" | sudo tee -a /etc/environment

# Restart services to pick up env var
sudo systemctl restart media-downloader-api

🟡 9. No HTTPS/TLS

Finding: Services run on HTTP only

Risk:

  • Passwords transmitted in clear text
  • Session tokens visible on network
  • Man-in-the-middle attacks

Fix: Use Let's Encrypt with Certbot:

sudo certbot --nginx -d yourdomain.com

🟢 10. Log Files Growing Unbounded

Finding:

  • service.log: 15MB
  • web-api.log: 2.3MB
  • No rotation configured

Risk: Disk space exhaustion

Fix: Already recommended in previous report (logrotate)


What's Secure (Good Practices Found)

Password Hashing: Using bcrypt (industry standard) JWT Implementation: Using jose library correctly Login Rate Limiting: 5 attempts, 15 min lockout SQL Injection: No f-string queries, using parameterized queries Session Management: Proper session table with expiration CORS (Dev): Restricted to localhost during development


Phase 1: IMMEDIATE (Do NOW - 1 hour total)

Priority 1: Enable Firewall (15 min)

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp  # SSH
sudo ufw allow 80/tcp  # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
sudo ufw status

Priority 2: Fix Database Permissions (5 min)

sudo chmod 600 /opt/media-downloader/database/*.db
sudo chmod 600 /opt/media-downloader/cookies/*.json

Priority 3: Set JWT Secret (5 min)

openssl rand -hex 32 | sudo tee /opt/media-downloader/.jwt_secret
echo "JWT_SECRET_KEY=$(cat /opt/media-downloader/.jwt_secret)" | sudo tee -a /etc/environment
sudo chmod 600 /opt/media-downloader/.jwt_secret
sudo systemctl restart media-downloader-api

Phase 2: URGENT (Do Today - 2-3 hours)

Priority 4: Add Authentication to API Endpoints (2 hours)

Create a comprehensive list of endpoints that need auth:

  • All DELETE operations
  • All POST operations (except /api/auth/login)
  • All configuration endpoints
  • All download/media access endpoints

Priority 5: Add Rate Limiting (1 hour)

Install and configure slowapi on all endpoints.


Phase 3: IMPORTANT (Do This Week)

Priority 6: Production Frontend Build

  • Stop Vite dev server
  • Configure nginx to serve static build
  • Remove development dependencies

Priority 7: HTTPS Setup

  • Obtain SSL certificate
  • Configure nginx for HTTPS
  • Redirect HTTP to HTTPS

Priority 8: Network Segmentation

  • Consider running services on localhost only
  • Use nginx as reverse proxy
  • Only expose nginx to network

Security Best Practices for Future

  1. Always require authentication - Default deny, explicitly allow
  2. Principle of least privilege - Restrict file permissions
  3. Defense in depth - Firewall + authentication + rate limiting
  4. Regular security audits - Review code and config quarterly
  5. Keep dependencies updated - Run npm audit and pip audit
  6. Monitor logs - Watch for suspicious activity
  7. Backup encryption keys - Store JWT secret securely

Testing Your Security

After implementing fixes, verify:

# 1. Firewall is active
sudo ufw status

# 2. Services not directly accessible
curl http://192.168.1.6:8000/api/downloads
# Should fail or require auth

# 3. File permissions correct
ls -la /opt/media-downloader/database/
# Should show -rw------- (600)

# 4. API requires auth
curl -H "Content-Type: application/json" \
  http://localhost/api/downloads
# Should return 401 Unauthorized

Questions?

Review this document and implement Phase 1 (IMMEDIATE) fixes right away. The firewall and file permissions take less than 30 minutes total but dramatically improve security.

Current Risk Level: 🔴 CRITICAL After Phase 1: 🟠 HIGH After Phase 2: 🟡 MEDIUM After Phase 3: 🟢 LOW