highYour server fetching attacker-chosen URLs
Server Fetches a URL Supplied by the Caller
The server will make a request to any address the caller supplies.
Why it matters
Your server sits inside your network and next to your cloud metadata service, database and internal admin tools. A fetch to an address chosen by the caller can reach those places on the caller's behalf. Limiting the destination to hosts you expect keeps the feature and removes the exposure.
What it looks like
This is the shape of code that triggers the rule. AI tools produce it because it works, and nothing tells them it is unsafe.
requests.get on a query parameter
resp = requests.get(request.args.get('url'))The smallest fix
minimal patch
from urllib.parse import urlparse
ALLOWED_HOSTS = {"api.github.com", "images.example.com"}
target = urlparse(url)
if target.scheme not in ("http", "https") or target.hostname not in ALLOWED_HOSTS:
abort(400)
resp = requests.get(url, timeout=5, allow_redirects=False)The better fix
If you have a few more minutes, this is the approach that holds up as the app grows.
safe alternative
# For open-ended features (link previews), resolve the hostname first and
# reject private, loopback and link-local ranges with the ipaddress
# module, disable redirects, and set a short timeout and a size limit.Let your AI tool fix it
When the scanner finds this in your project, it fills in the file and line for you. This is the prompt it gives you to paste into Claude Code, Cursor or whatever you use.
In [the file] at line [the line number] the server fetches a URL from the request: [the flagged code]. Parse it with urlparse, allow only http/https, and either compare the hostname to an allow-list or reject private, loopback and link-local addresses after DNS resolution. Disable redirects, add a timeout and return 400 for anything rejected.
How to check the fix worked
1. Send url=http://127.0.0.1:8000/ and confirm a 400. 2. Send url=http://169.254.169.254/ and confirm a 400. 3. Send an allowed URL and confirm the feature still works.