rules:
  - id: auth.py.secret.flask-hardcoded-key
    languages:
      - python
    severity: ERROR
    message: |
      The Flask `SECRET_KEY` (used to sign session cookies and CSRF tokens) is
      set to a hard-coded string literal. Anyone who reads the source (or a
      leaked repo) can forge session cookies and impersonate any user, a
      complete authentication bypass (CWE-798).

      Load the secret from the environment or a secret manager instead, e.g.
      `app.secret_key = os.environ["SECRET_KEY"]`, and generate it with a CSPRNG
      such as `secrets.token_hex(32)` / `os.urandom(32)`. Never commit the value.
    # Scoped to Flask's secret-key assignment. `$APP` matches any app variable
    # name. The `"..."` pattern matches ONLY a string-literal value, so secrets
    # loaded from os.environ / config refs / os.urandom() are NOT flagged.
    pattern-either:
      - pattern: $APP.secret_key = "..."
      - pattern: $APP.config["SECRET_KEY"] = "..."
      - pattern: $APP.config.update(..., SECRET_KEY="...", ...)
    metadata:
      oauthlint-rule-id: AUTH-PY-SECRET-001
      oauthlint-doc-url: https://oauthlint.dev/rules/py-secret-flask-hardcoded-key
      category: security
      cwe: CWE-798
      owasp: A07:2021
      llm-prevalence: HIGH
      technology:
        - flask
      references:
        - https://flask.palletsprojects.com/en/stable/config/#SECRET_KEY
        - https://cwe.mitre.org/data/definitions/798.html
