2025-12-21

Your Flask App Is Probably Leaking Something — Run These 7 Commands

Python, Security, DevOps · Dorian Sotpyrc

Why this matters

Most Flask “leaks” aren’t cinematic hacks. They’re boring misconfigurations: debug flags left on, apps binding to a public interface, secrets copied into repos, or logs quietly capturing tokens.

Server security checks for a Flask deployment
A quick, repeatable checklist to catch the most common Flask deployment leaks.
Before you run anything

These checks are designed to be fast and low-risk. Run them on the server/container where Flask is deployed. If you’re on shared infrastructure, avoid printing full secrets into terminal history or logs.

Goal: find the “oops” settings — debug mode, accidental public exposure, world-readable config, risky file perms, and credentials sitting in places you forgot about.

The 7 commands

1) Confirm what’s listening on the network

This tells you what ports are open and which processes own them. On a typical secure setup, you’ll see your reverse proxy (Nginx/Caddy/Traefik) listening publicly on 443 (HTTPS) — and your Flask app listening only on a local/private interface.

BASH
sudo ss -lntup

2) Verify your app is NOT bound publicly

You don’t want Gunicorn/Flask binding to 0.0.0.0 (public) unless you have a very specific reason. The safe default is: reverse proxy handles HTTPS on 443, and the app binds to 127.0.0.1 (or a private network interface) on an internal port.

BASH
ps aux | egrep -i 'gunicorn|flask|uvicorn' | egrep -v egrep

3) Check for DEBUG / development settings

Debug mode can leak stack traces, config, and sometimes interactive consoles (depending on setup). Make sure it’s not enabled via env vars or systemd.

BASH
env | egrep -i 'FLASK_ENV|FLASK_DEBUG|DEBUG|ENVIRONMENT' || true

4) Hunt for accidental secrets in the app folder

The usual culprits: .env, copied config files, token dumps, “temporary” debug JSON, or backups.

BASH
cd /path/to/your/app && \
find . -maxdepth 3 -type f \( \
  -name ".env" -o -name "*.env" -o -name "*secret*" -o -name "*token*" -o -name "*key*" -o -name "*.pem" -o -name "*.p12" -o -name "*.pfx" -o -name "*.bak" \
\ ) -print

5) Check for world-readable files (quiet but deadly)

Anything containing credentials should not be readable by “other”. This surfaces obvious permission mistakes.

BASH
cd /path/to/your/app && \
find . -type f -perm -o=r -maxdepth 4 -print 2>/dev/null | head -n 200

6) Scan recent logs for “oops” strings

You’re not trying to be perfect here — you’re trying to catch obvious leaks: Authorization:, Bearer, api_key, secret, etc.

BASH
sudo journalctl -u your-service-name --since "24 hours ago" --no-pager | \
egrep -i 'authorization:|bearer |api[_-]?key|secret|token|password' | tail -n 200

7) Confirm what’s reachable from the outside (default HTTPS)

Run this from a different machine (or your laptop) to see what the internet sees. HTTPS defaults to port 443, so you should not need to specify a port.

BASH
curl -sS -D- https://your-domain.com/healthz -o /dev/null

What “good” looks like

  • Your reverse proxy handles the public edge on 443 (HTTPS).
  • Your app binds to 127.0.0.1 (or a private interface) — not 0.0.0.0.
  • Debug flags are off. Stack traces are not served publicly.
  • Secrets live in env vars / secret managers — not committed files or logs.
  • Logs do not contain auth headers or bearer tokens.

Next steps: the fast fixes

  • Terminate TLS at Nginx/Caddy/Traefik and forward to your app privately.
  • Disable debug everywhere (env vars, config, systemd, container args).
  • Move secrets into environment variables (or a secret store) and rotate anything that leaked.
  • Lock down file permissions: configs and keys should not be world-readable.
  • Add a minimal /healthz endpoint and monitor it.

Related PLEX reading

References & further reading