Safeguard
Security Guides•

What does Django DEBUG = True expose if you leave it on in production?

Django DEBUG = True leaks source excerpts, local variables, settings and library details on error pages. What it shows, how to check, and how to fix it.

Safeguard Security Team
4 min read

Leaving DEBUG = True in production makes Django show detailed error pages that include source code excerpts, local variables, settings and the libraries in use. That is a map of your application handed to anyone who can trigger an error. Set DEBUG to False, set ALLOWED_HOSTS, and send errors to logging instead.

What the Django docs say it leaks

The deployment checklist is blunt: you must never enable debug in production. It explains that DEBUG = True is convenient in development because it gives full tracebacks in the browser, but in production it "leaks lots of information about your project", listing excerpts of your source code, local variables, settings and libraries used.

Think about what each item is worth to an attacker:

Leaked itemWhy it helps an attacker
Source excerptsShows logic, query construction and validation gaps
Local variablesCan include tokens, user data and connection details
SettingsReveals installed apps, middleware, paths and debug flags
Library listLets them match versions against known advisories

You do not need a vulnerability for this to matter. Any unhandled exception, even one an attacker provokes with a malformed request, becomes a reconnaissance report.

Why it stays on by accident

Most cases are not careless. They come from a shared settings file where DEBUG defaults to True, an environment variable that parses the string "False" as truthy, a staging server that became production, or a hotfix someone forgot to revert. Because the site works fine with debug on, nothing breaks to warn you.

A safer pattern is to default to False and require an explicit opt in:

import os

DEBUG = os.environ.get("DJANGO_DEBUG", "") == "1"

With this, a missing variable means production behavior.

How to check a running site

  1. Run python manage.py check --deploy against your production settings file. The checklist says it automates some of its checks.
  2. In a staging copy, trigger a harmless error and confirm you see a plain error page.
  3. Search your repositories and images for settings files that hardcode DEBUG = True.

What to do instead of debug pages

Django's error reporting guide says to turn DEBUG off on public sites, and that running with DEBUG False means you will not see errors unless you configure reporting. When DEBUG is False and the ADMINS setting is configured with working email, Django emails administrators for responses with status 500 or above. Better still, send exceptions to your logging or error tracking system. Use the sensitive_variables and sensitive_post_parameters decorators so reports do not carry secrets.

Also note that DEBUG = False requires ALLOWED_HOSTS to be set, because Django does not work without a suitable value in that mode.

Try it yourself

Click through it at your own pace, or open it full screen. Watch how a running web app is probed from the outside, the same view an attacker has of a debug page.

Quick check

Is DEBUG = True a vulnerability or a misconfiguration?

A misconfiguration. Django is working as designed, but the information it exposes helps an attacker find real weaknesses.

Does check --deploy catch it?

It automates some of the deployment checklist, and Django says to run it against your production settings file. Treat it as a helper, and still review DEBUG yourself.

Safeguard's SAST and policy gates can flag hardcoded debug flags in a pull request, and compliance evidence automation can record the check. A free scan is available.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.