python.django.security.django-no-csrf-token.django-no-csrf-token

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Manually-created forms in django templates should specify a csrf_token to prevent CSRF attacks

Run Locally

Run in CI

Defintion

rules:
  - id: django-no-csrf-token
    patterns:
      - pattern: <form...>...</form>
      - pattern-either:
          - pattern: |
              <form ... method="$METHOD" ...>...</form>
          - pattern: |
              <form ... method='$METHOD' ...>...</form>
          - pattern: |
              <form ... method=$METHOD ...>...</form>
      - metavariable-regex:
          metavariable: $METHOD
          regex: (?i)(post|put|delete|patch)
      - pattern-not-inside: <form...>...{% csrf_token %}...</form>
      - pattern-not-inside: <form...>...{{ $VAR.csrf_token }}...</form>
    message: Manually-created forms in django templates should specify a csrf_token
      to prevent CSRF attacks
    languages:
      - generic
    severity: WARNING
    metadata:
      category: security
      cwe: "CWE-352: Cross-Site Request Forgery (CSRF)"
      references:
        - https://docs.djangoproject.com/en/4.2/howto/csrf/
      confidence: MEDIUM
      likelihood: MEDIUM
      impact: MEDIUM
      subcategory:
        - guardrail
      technology:
        - django
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cross-Site Request Forgery (CSRF)
    paths:
      include:
        - "*.html"

Examples

django-no-csrf-token.html

<div class="container">
  <div class="row">
      <div class="col-6">
<!-- ruleid: django-no-csrf-token -->
          <form method="post">
              <input type="text" name="some_field">Some Field</input>
              <input type="submit" name="submit">Submit</input>
          </form>
      </div>
  </div>
</div>

<div class="container">
  <div class="row">
      <div class="col-6">
<!-- ruleid: django-no-csrf-token -->
          <form method='POST'>
              <input type="text" name="some_field">Some Field</input>
              <input type="submit" name="submit">Submit</input>
          </form>
      </div>
  </div>
</div>

<div class="container">
  <div class="row">
      <div class="col-6">
<!-- ruleid: django-no-csrf-token -->
          <form method='PUT'>
              <input type="text" name="some_field">Some Field</input>
              <input type="submit" name="submit">Submit</input>
          </form>
      </div>
  </div>
</div>

<div class="container">
  <div class="row">
      <div class="col-6">
          <form method="post">
<!-- ok: django-no-csrf-token -->
            {% csrf_token %}
              <input type="text" name="some_field">Some Field</input>
              <input type="submit" name="submit">Submit</input>
          </form>
      </div>
  </div>
</div>

<div class="container">
  <div class="row">
      <div class="col-6">
          <form method="delete">
<!-- ok: django-no-csrf-token -->
            {% csrf_token %}
              <input type="text" name="some_field">Some Field</input>
              <input type="submit" name="submit">Submit</input>
          </form>
      </div>
  </div>
</div>

<div class="container">
  <div class="row">
      <div class="col-6">
<!-- ok: django-no-csrf-token -->
          <form>
              <input type="text" name="some_field">Some Field</input>
              <input type="submit" name="submit">Submit</input>
          </form>
      </div>
  </div>
</div>

<div class="container">
  <div class="row">
      <div class="col-6">
<!-- ok: django-no-csrf-token -->
          <form method="GET">
              <input type="text" name="some_field">Some Field</input>
              <input type="submit" name="submit">Submit</input>
          </form>
      </div>
  </div>
</div>

<div class="container">
  <div class="row">
      <div class="col-6">
<!-- ok: django-no-csrf-token -->
        <form method="POST" action="{{ url_for('web.organization_settings') }}">
          {{ name_form.csrf_token }}
          {{ render_form_row([name_form.organization_name], col_map={'organization_name': 'col-md-6'}) }}
        
          <input type="submit" value="Submit" class="btn btn-primary">
        </form>
      </div>
  </div>
</div>