T09 · Insecure Skill Coding Practices
- Location
scripts/format.py:6- Finding
Unrestricted URL Fetching Enables Blind Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/format.py, lines 6 and 15–16, with attacker-controlled input entering at lines 68–70
Vulnerability Type: Blind server-side request forgery through an unrestricted URL fetch
Risk Level: MediumVulnerable Code
python def fetch_and_format_stock_data(api_url): """ 仅使用 Python 标准库调用接口并构建 AI 友好结构 """ headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } try: req = urllib.request.Request(api_url, headers=headers) with urllib.request.urlopen(req) as response: if response.getcode() != 200: return {"error": f"HTTP Error: {response.getcode()}"}The URL originates directly from a command-line argument:
python api_url = sys.argv[1] result = fetch_and_format_stock_data(api_url)Technical Analysis
The script passes an arbitrary command-line URL directly to
urllib.request.Requestandurllib.request.urlopen. It does not:- Restrict the URL scheme to HTTPS.
- Restrict the destination to the documented Yahoo Finance host.
- Reject embedded credentials or nonstandard ports.
- Resolve and block loopback, private, link-local, reserved, or cloud metadata addresses.
- Validate redirect destinations.
- Apply a network timeout.
Although the documented purpose is to retrieve Yahoo Finance chart data, the implementation can send a GET request to any destination reachable from the runtime environment. This creates a blind SSRF primitive.
Direct response disclosure is constrained because the response is subsequently parsed as Yahoo Finance JSON. Nevertheless, differences in returned errors, status behavior, and timing may reveal whether an internal endpoint exists or is reachable. GET requests can also affect internal services whose endpoints perform actions without proper authorization.
Attack Path
- An attacker influences the URL passed to the formatter, such as through ...[truncated 1338 chars]
- Remediation
View remediation
Remediation Suggestions
- Replace arbitrary URL input with a validated market symbol and construct the Yahoo Finance URL internally.
- If URL input must remain supported, parse it with
urllib.parse.urlsplitand permit only:- The
httpsscheme. - The exact approved hostname, such as
query1.finance.yahoo.com. - The default HTTPS port.
- The
- Reject URLs containing user-information components, malformed hostnames, fragments, or unexpected ports.
- Resolve the hostname before connecting and reject all loopback, private, link-local, multicast, reserved, and unspecified IPv4 and IPv6 addresses using the
ipaddressmodule. - Disable automatic redirects or validate every redirect target with the same scheme, hostname, port, and IP-address controls.
- Add a short explicit timeout:
python with urllib.request.urlopen(req, timeout=10) as response: - Validate that the path matches the expected Yahoo Finance chart endpoint and that query parameters use an allowlist of supported values.
- Return generic network errors to reduce endpoint enumeration through detailed failure messages and timing differences.
- Run the skill in an environment with outbound network controls that deny access to loopback, private networks, and cloud metadata addresses unless explicitly required.
