Skip to content

Security: jly-engineer/threat_intelligence_app

Security

SECURITY.md

ThreatPilot Security Guide

This document outlines security measures implemented in ThreatPilot and best practices for deployment.


Critical Security Fixes Applied

1. Secret Rotation (Completed ✓)

What was done:

  • Generated new SECRET_KEY using cryptographically secure randomness
  • Generated new DEFAULT_ADMIN_PASSWORD (strong, 43-character, URL-safe)
  • Cleared NVD_API_KEY (regenerate from https://nvd.nist.gov/developers/request-an-api-key)
  • All credentials in .env have been rotated

Action Items:

  • IMMEDIATELY: Treat the old NVD API key as compromised. Request a new one from https://nvd.nist.gov/developers/request-an-api-key
  • Update database credentials if using the example password
  • Generate new secrets for each deployment environment:
    python -c "import secrets; print('SECRET_KEY=' + secrets.token_hex(32))"
    python -c "import secrets; print('DEFAULT_ADMIN_PASSWORD=' + secrets.token_urlsafe(32))"

2. Enforce Strong Admin Password (Completed ✓)

What was done:

  • app.py now validates DEFAULT_ADMIN_PASSWORD on startup
  • Rejects passwords shorter than 12 characters
  • Rejects known weak defaults: "", "changeme", "admin123", "password", etc.
  • Application will refuse to start with weak passwords

Before Deploying:

  • Set a unique, strong password (min 12 chars)
  • Never use default or test passwords in production
  • Store securely in .env (which is in .gitignore)

3. SSRF Prevention in Webhooks (Completed ✓)

What was done:

  • Added _is_valid_webhook_url() function to validate webhook URLs
  • Blocks all non-HTTPS URLs (http://, file://, gopher://, etc.)
  • Blocks private IP ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • Blocks loopback addresses (127.0.0.1, ::1, localhost)
  • Blocks link-local, multicast, and reserved IPs
  • Webhook settings form now validates before saving

Webhook Security Best Practices:

  • Only HTTPS endpoints are accepted
  • Webhook receivers should verify X-Signature headers (when implemented)
  • Keep webhook endpoint URLs private
  • Monitor webhook delivery logs for suspicious activity

4. Search Engine Indexing Prevention (Completed ✓)

What was done:

  • Created static/robots.txt blocking all search engine crawlers
  • Added /robots.txt route in app.py to serve with proper headers
  • Disallows all sensitive paths: /auth/, /settings/, /cves/, etc.
  • Applied to all user-agent strings (Google, Bing, etc.)

Additional Protections:

  • X-Robots-Tag: noindex header recommended (add to CSP if needed)
  • Set search engines to avoid indexing via webmaster tools
  • Monitor Google Search Console for any indexed pages

5. Pre-Commit Hook to Block Secrets (Completed ✓)

What was done:

  • Created .git/hooks/pre-commit hook
  • Prevents accidental commits of .env and other sensitive files
  • Blocks patterns: .env*, *.key, *.pem, credentials.json, etc.
  • Can be bypassed with --no-verify if absolutely necessary (not recommended)

Verification:

# Test the hook by attempting to stage .env
git add .env
git commit -m "test"  # Should be blocked

# To commit anyway (avoid unless necessary):
git commit --no-verify  # NOT RECOMMENDED

Cleaning Up Git History (If .env was exposed)

If .env was pushed to a remote repository before these changes:

Option 1: Using git filter-repo (Recommended)

# Install if needed: pip install git-filter-repo

# Remove all traces of .env from history
git filter-repo --path .env --invert-paths

# Force push to remote (DANGEROUS — coordinate with team)
git push --force-with-lease

Option 2: Using BFG Repo-Cleaner

# Install: apt-get install bfg  (or download from GitHub)

# Remove all traces of .env
bfg --delete-files .env

# Force push
git push --force-with-lease

Option 3: Manual Rebase (For small repos)

# Interactive rebase to the first commit
git rebase -i --root

# Mark commits that added .env as 'edit'
# Then remove the file and amend: git rm .env && git commit --amend

# Force push
git push --force-with-lease

After Cleaning History:

  1. Notify all team members to re-clone from the cleaned repository
  2. Rotate all secrets that were exposed (database password, API keys, SECRET_KEY, admin password)
  3. Check if any secrets were deployed to production and rotate those too
  4. Update any external services that may have been using the old credentials

Secure Deployment Checklist

  • All secrets are unique per environment (dev, staging, production)
  • .env is in .gitignore and never committed
  • SECRET_KEY is at least 32 bytes of random data
  • DEFAULT_ADMIN_PASSWORD is at least 12 characters, randomly generated
  • Database credentials use strong passwords
  • NVD API key is registered and valid (or left blank)
  • Webhook URL (if configured) is a valid HTTPS public endpoint
  • HTTPS is enabled in production (HTTPS=1 in .env)
  • Session cookies have Secure flag (requires HTTPS)
  • CSP headers are applied (already in app.py)
  • robots.txt is served and prevents indexing
  • Database backups are encrypted and stored securely
  • Logs are not exposed publicly and contain no secrets
  • Rate limiting is configured for API endpoints
  • CSRF protection is enabled (Flask-WTF, already in app.py)
  • SQL injection is prevented (SQLAlchemy ORM, already in use)
  • XSS is prevented (Jinja2 auto-escaping, already in templates)

Ongoing Security Practices

Secrets Rotation Schedule

  • Rotate SECRET_KEY annually or after any suspected compromise
  • Rotate DEFAULT_ADMIN_PASSWORD every 90 days
  • Rotate database credentials every 180 days
  • Rotate API keys every 12 months

Dependency Updates

# Check for vulnerabilities in dependencies
pip list --outdated
pip check

# Update all packages
pip install --upgrade -r requirements.txt

Monitoring & Logging

  • Monitor webhook delivery failures (may indicate SSRF attempts)
  • Monitor failed login attempts (IP address rate limiting)
  • Monitor database query logs for injection attempts
  • Monitor file access logs for unauthorized report downloads

Incident Response

If you suspect a compromise:

  1. Immediately rotate all secrets

    # Generate new ones
    python -c "import secrets; print(secrets.token_hex(32))"
  2. Check git history for exposed files

    git log -S "password" --oneline
    git log -S "api_key" --oneline
  3. Clean up if found (use git filter-repo as above)

  4. Update CLAUDE.md with incident details and lessons learned


Security Headers Reference

ThreatPilot sets these security headers automatically (in app.py):

X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net...

These prevent:

  • MIME-type sniffing attacks
  • Clickjacking/framing attacks
  • Information leakage via Referer
  • Unauthorized camera/mic access

Reporting Security Issues

If you discover a vulnerability in ThreatPilot:

  1. Do NOT post it publicly or commit a fix immediately
  2. Document it with reproduction steps
  3. Contact the maintainer privately
  4. Wait for a response before disclosing
  5. Allow time for patching (typically 30 days)

For this project, consult CLAUDE.md for the current maintainer's contact.


References


Last Updated: 2026-04-12 Status: All critical vulnerabilities patched

There aren't any published security advisories