v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: HIGH auth.py.secret.django-hardcoded-key

The Django SECRET_KEY is set to a hard-coded string literal in settings.

Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.

Why this matters

This is typically the auto-generated django-insecure-... value committed by mistake. SECRET_KEY signs sessions, CSRF tokens and password-reset tokens. Anyone who reads the source or a leaked repo can forge them and bypass authentication entirely (CWE-798).

Load it from the environment or a secret manager instead, e.g. SECRET_KEY = os.environ["SECRET_KEY"], django-environ (env("SECRET_KEY")), or config("SECRET_KEY"). Generate the value with a CSPRNG and never commit it.

VULNERABLE
vulnerable.py
# Django settings.py

# ruleid: auth.py.secret.django-hardcoded-key
SECRET_KEY = "django-insecure-9v8x2k!q3@w5z#r7t1y4u6i8o0p-abcdefghijklmno"

# ruleid: auth.py.secret.django-hardcoded-key
SECRET_KEY = "my-arbitrary-super-secret-key"

# SECURITY WARNING: keep the secret key used in production secret!
# ruleid: auth.py.secret.django-hardcoded-key
SECRET_KEY = "another-key-with-a-comment-around-it"  # do not share
SAFE
safe.py
# Django settings.py

import os

import environ
from decouple import config

env = environ.Env()

# ok: auth.py.secret.django-hardcoded-key
SECRET_KEY = os.environ["SECRET_KEY"]

# ok: auth.py.secret.django-hardcoded-key
SECRET_KEY = os.environ.get("SECRET_KEY")

# ok: auth.py.secret.django-hardcoded-key
SECRET_KEY = env("SECRET_KEY")

# ok: auth.py.secret.django-hardcoded-key
SECRET_KEY = config("SECRET_KEY")

_loaded_key = os.environ["SECRET_KEY"]
# ok: auth.py.secret.django-hardcoded-key
SECRET_KEY = _loaded_key

Suppressing this rule

If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.

# oauthlint-disable-next-line auth.py.secret.django-hardcoded-key -- <reason>

References

https://docs.djangoproject.com/en/stable/ref/settings/#secret-key ↗https://cwe.mitre.org/data/definitions/798.html ↗