Framework audits/Django

Django Security Audit

What should a Django security audit check?

Django's protections are strong but almost all configurable, so the audit is largely a settings audit. The findings that matter are debug mode left enabled in production, the secret key committed in settings, a permissive allowed-hosts list, raw SQL bypassing the ORM's parameterisation, and an admin interface reachable at its default path.

Django ships with CSRF protection, ORM parameterisation and XSS escaping switched on, which means most Django vulnerabilities are not gaps in the framework but places where a developer stepped around it.

Where Django codebases actually break

These are patterns we look for in code produced this way — not flaws in Django itself. Each names the check that finds it.

Debug mode still enabled in production

With debug enabled, an unhandled exception renders a full traceback including local variables, installed applications and substantial configuration detail to whoever triggered it. Because it is the default during development and only harmful once deployed, it is the single most common serious Django misconfiguration.

Detected by: Unvalidated request input

The secret key living in settings.py

Django's secret key signs sessions and password-reset tokens. A project generated from the default template has it written literally into settings, and that file is normally committed. Anyone with the key can forge a session cookie, which makes it functionally an authentication bypass rather than a configuration detail.

Detected by: Hardcoded secret value

Raw queries stepping around the ORM

The ORM parameterises by default, so Django SQL injection almost always arrives through the deliberate escape hatches — raw query methods and cursor execution — where a developer has interpolated a value into the string rather than passing it as a parameter.

Detected by: Unparameterized database query

A wildcard in allowed hosts

Setting the allowed-hosts list to accept any host removes Django's host-header validation. That enables cache poisoning and makes password-reset links generated from the request host forgeable, sending a working reset token to a domain the attacker controls.

Detected by: Unvalidated request input

Auditing a Django codebase: the short list

  • Confirm debug is false in every deployed environment, not merely absent from the default settings module
  • Check whether the secret key is read from the environment, and rotate it if it has ever been committed
  • Grep for raw query and cursor-execute calls and confirm every one passes parameters rather than interpolating
  • Verify the allowed-hosts list names real hosts and contains no wildcard
  • Check whether the admin is exposed at its default path and whether it should be reachable publicly at all

Scan your Django codebase

Every check named above runs automatically. Free on public repositories, no signup, results in under three minutes — with the file and line for each finding.

Frequently asked questions

Is Django secure out of the box?

More so than most frameworks. CSRF protection, ORM parameterisation and template escaping are on by default, so the common web vulnerabilities are handled unless someone deliberately steps around them. The risk sits in configuration and in the escape hatches, not in the defaults.

What is the most common Django security mistake?

Debug mode left on in production. It renders a traceback containing configuration and local variables to anyone who can trigger an exception, and because it is the correct setting during development it survives to deployment more often than any other misconfiguration.

Can Django have SQL injection?

Yes, but almost only through the escape hatches. The ORM parameterises queries, so injection arrives when someone uses a raw query or a database cursor and builds the statement by string interpolation instead of passing parameters.

Related reading