Skip to content

Feature request (with my own implementation): add a plugin which detects common SSRF cases where user-controlled URLs flow into outbound HTTP requests #1401

Description

@invoke1442

Is your feature request related to a problem? Please describe.
Yes. Bandit currently misses a common SSRF pattern in Python services: user-controlled URLs from request data flowing into outbound HTTP clients such as requests, httpx, or urllib.

The existing HTTP-related plugins do not really cover this:

  • B113 checks missing timeout
  • B501 checks verify=False
  • B615 is specific to Hugging Face downloads

So in practice, Bandit can miss real SSRF bugs in code that downloads files or resources from user-provided URLs.

A concrete example is CVE-2025-54381 in BentoML:

  • Advisory: https://github.com/advisories/GHSA-mrmq-3q62-6cc8
  • Fix: https://github.com/bentoml/BentoML/commit/534c3584621da4ab954bdc3d814cc66b95ae5fb8

Similar issues also show up in projects like LLaMA-Factory (CVE-2025-61784), LNbits (CVE-2025-32013), and D-Tale (CVE-2024-21642).

Describe the solution you'd like
I would like Bandit to have a plugin for SSRF-style flows where:

  • the source is request-controlled input such as request.body(), request.args, request.form(), request.query_params, or request.get_json()
  • the sink is an outbound HTTP call such as:
    • requests.*
    • httpx.*
    • urllib.request.urlopen
    • aiohttp.ClientSession.*

It would also be useful if the plugin understood common safety guards, for example helpers like is_safe_url(url) or similar allowlist/private-address checks, so fixed code does not keep getting flagged.

Describe alternatives you've considered
A few alternatives came up:

  • Relying on existing Bandit plugins: this does not solve the problem, because the current plugins around HTTP calls check hygiene issues, not untrusted URL flow.
  • Keeping this in heavier dataflow tools only, such as CodeQL: that works, but Bandit is often used as a lightweight scanner, and this is a common enough pattern that it would be valuable to catch here too.
  • A broader "untrusted data to external API" plugin: I tried that approach, but it produced noise by flagging non-network calls. Narrowing it to real network sinks worked much better.

The plugin prototype I implemented was inspired by CodeQL’s rule py/count-untrusted-data-external-api.
It works well on my projects, and it successfully detects CVE-2025-54381 and CVE-2025-61784 and avoids FPs in their fixed commits.

external-api-untrusted-data.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions