rules:
  - id: auth.py.secret.django-hardcoded-key
    languages:
      - python
    severity: ERROR
    message: |
      The Django `SECRET_KEY` is set to a hard-coded string literal in
      settings. 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.
    # Scoped to a module-level `SECRET_KEY = "<literal>"` assignment. The
    # `"..."` pattern matches ONLY a string-literal value, so secrets loaded
    # from os.environ / env() / config() / a variable are NOT flagged.
    pattern: SECRET_KEY = "..."
    metadata:
      oauthlint-rule-id: AUTH-PY-SECRET-002
      oauthlint-doc-url: https://oauthlint.dev/rules/py-secret-django-hardcoded-key
      category: security
      cwe: CWE-798
      owasp: A07:2021
      llm-prevalence: HIGH
      technology:
        - django
      references:
        - https://docs.djangoproject.com/en/stable/ref/settings/#secret-key
        - https://cwe.mitre.org/data/definitions/798.html
