PyCQA / PyCQA/bandit

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

Open
#1,401 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
Python
Stars
8.3k
Forks
836
Avg merge
5d 3h
Merged PRs (30d)
1

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the attached external-api-untrusted-data.zip prototype and the issue's listed request-controlled sources and outbound HTTP sinks. Compare its behavior with the existing Bandit HTTP plugins, then define tests for detecting the vulnerable flows while avoiding code protected by safety guards; done means the plugin reliably covers the described SSRF cases without the noted false positives.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
devtools, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.