python.requests.best-practice.use-raise-for-status.use-raise-for-status

profile photo of semgrepsemgrep
Author
5,027
Download Count*

There's an HTTP request made with requests, but the raise_for_status() utility method isn't used. This can result in request errors going unnoticed and your code behaving in unexpected ways, such as if your authorization API returns a 500 error while you're only checking for a 401.

Run Locally

Run in CI

Defintion

rules:
  - id: use-raise-for-status
    patterns:
      - pattern-either:
          - pattern: requests.request(...)
          - pattern: requests.get(...)
          - pattern: requests.post(...)
          - pattern: requests.put(...)
          - pattern: requests.delete(...)
          - pattern: requests.head(...)
          - pattern: requests.patch(...)
      - pattern-not-inside: |
          $RESP = requests.$METHOD(...)
          $RESP.raise_for_status(...)
      - pattern-not-inside: |
          requests.$METHOD(...).raise_for_status(...)
      - pattern-not-inside: |
          $RESP = requests.$METHOD(...)
          if $RESP.status_code == ...:
            ...
      - pattern-not-inside: |
          $RESP = requests.$METHOD(...)
          if $RESP.status_code != ...:
            ...
      - pattern-not-inside: |
          $RESP = requests.$METHOD(...)
          ...
          if $RESP.ok:
            ...
      - pattern-not-inside: |
          $RESP = requests.$METHOD(...)
          ...
          if not $RESP.ok:
            ...
      - pattern-not-inside: |
          with ...:
            ...
            $RESP = requests.$METHOD(...)
            ...
          $RESP.raise_for_status(...)
      - pattern-not-inside: |
          with ... as ...:
            ...
            $RESP = requests.$METHOD(...)
            ...
          $RESP.raise_for_status(...)
    message: There's an HTTP request made with requests, but the raise_for_status()
      utility method isn't used. This can result in request errors going
      unnoticed and your code behaving in unexpected ways, such as if your
      authorization API returns a 500 error while you're only checking for a
      401.
    metadata:
      references:
        - https://requests.readthedocs.io/en/master/api/#requests.Response.raise_for_status
      category: best-practice
      technology:
        - requests
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    severity: WARNING
    languages:
      - python

Examples

use-raise-for-status.py

import requests

# ruleid:use-raise-for-status
requests.put("")

requests.put
requests.put("").raise_for_status("")

def f():
    # ruleid:use-raise-for-status
    return requests.get("")

def f():
    # ruleid:use-raise-for-status
    return requests.post("")

def f():
    # ruleid:use-raise-for-status
    return requests.put("")

def f():
    # ruleid:use-raise-for-status
    return requests.patch("")

def f():
    # ruleid:use-raise-for-status
    return requests.delete("")

def f():
    # ruleid:use-raise-for-status
    requests.put("")

def f():
    # ruleid:use-raise-for-status
    r = requests.get("")
    return r

def f():
    # ruleid:use-raise-for-status
    r = requests.get("")
    r.raise_for_status
    return r

def f():
    # ok:use-raise-for-status
    r = requests.get("")
    r.raise_for_status()
    # ruleid:use-raise-for-status
    r = requests.get("")
    r.raise_for_status
    return r

def f():
    # ruleid:use-raise-for-status
    r = requests.get("")
    r.raise_for_status
    # ok:use-raise-for-status
    r = requests.get("")
    r.raise_for_status()
    return r

def f():
    # ok:use-raise-for-status
    r = requests.get("")
    r.raise_for_status()
    return r

def f():
    # ok:use-raise-for-status
    r = requests.get("")
    if r.status_code != requests.codes.ok:
        logging.error("Something awful happened", r)
    return r

def f():
    # ok:use-raise-for-status
    r = requests.get("")
    if not r.ok:
        logging.error("Something awful happened", r)
    return r

def f():
    # ok:use-raise-for-status
    r = requests.get("")
    if r.ok:
        return r

def f():
    # ok:use-raise-for-status
    requests.put("").raise_for_status()

def f():
    # ok:use-raise-for-status
    from contextlib import nullcontext
    with nullcontext():
        r = requests.post("")
    r.raise_for_status()

def f():
    # ok:use-raise-for-status
    from contextlib import nullcontext
    with nullcontext(value) as value:
        r = requests.post("")
    r.raise_for_status()

def f():
    # ok:use-raise-for-status
    with open("file.txt", mode="r") as f:
        logging.debug("Opened file for uploading.")
        r = requests.post("", files={"file": f})
        logging.debug("Request finished. Closing file before checking status.")
    r.raise_for_status()