T09 · Insecure Skill Coding Practices
- Location
scripts/find_channel_id.py:17- Finding
Arbitrary URL Fetch Enables Server-Side Request Forgery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/find_channel_id.py, lines 17–24 and 28–30
Vulnerability Type: Server-Side Request Forgery (SSRF) caused by inadequate URL validation
Risk Level: MediumVulnerable Code
python if channel_input.startswith('@'): url = f"https://www.youtube.com/{channel_input}" elif channel_input.startswith('UC'): return channel_input # Already a channel ID elif 'youtube.com/' in channel_input or 'youtu.be/' in channel_input: url = channel_input else: # Assume it's a channel name url = f"https://www.youtube.com/{channel_input}" try: # Fetch channel page req = Request(url, headers={'User-Agent': 'Mozilla/5.0'}) response = urlopen(req, timeout=10) html = response.read().decode('utf-8')Technical Analysis
The utility accepts an input as a YouTube URL whenever the raw string contains
youtube.com/oryoutu.be/. A substring match does not establish that the destination hostname belongs to YouTube.For example,
http://127.0.0.1:8080/youtube.com/satisfies the substring check even though its destination is the local host. The complete attacker-controlled value is then passed tourlopen(). The implementation does not enforce HTTPS, validate the parsed hostname or port, reject local and private addresses, or constrain redirects. Python's URL opener follows HTTP redirects by default, so even an initially permitted destination could redirect the request elsewhere.This outbound-fetch capability exceeds the utility's minimum requirement, which only requires requests to known YouTube hosts.
Attack Path
- An attacker supplies a crafted argument to
find_channel_id.py, directly or through an agent workflow that forwards user-provided channel input. - The argument contains a permitted substring but names an unintended destination, for example:
text http://127.0.0.1:8080/youtube.com/ - The condition at lines 21–22 accepts the entire string as a va ...[truncated 1156 chars]
- An attacker supplies a crafted argument to
- Remediation
View remediation
Remediation Suggestions
- Prefer accepting only YouTube handles and syntactically valid channel IDs. Avoid accepting arbitrary URLs unless necessary.
- Parse URLs with
urllib.parse.urlparse()and require:- Scheme exactly equal to
https - No embedded username or password
- No unexpected port
- Hostname exactly equal to an explicit allowlisted hostname, such as
www.youtube.com,youtube.com,m.youtube.com, oryoutu.be
- Scheme exactly equal to
- Do not use suffix-only or substring-based hostname checks. A value such as
youtube.com.attacker.examplemust not be accepted. - Resolve the hostname and reject loopback, private, link-local, multicast, reserved, and unspecified IP addresses using Python's
ipaddressmodule. - Disable automatic redirects or validate every redirect target against the same scheme, hostname, port, and resolved-address policy.
- Apply a response-size limit before reading the body to reduce memory-exhaustion risk.
- Keep the existing timeout and consider separate connection and read limits where the HTTP client supports them.
- Add regression tests for malicious inputs, including:
text http://127.0.0.1/youtube.com/ http://169.254.169.254/youtube.com/ https://youtube.com.attacker.example/ https://attacker.example/youtube.com/ https://user@attacker.example/youtube.com/ - For the main fetcher, continue restricting API calls to Google's documented HTTPS endpoint. Restrict the YouTube API key to YouTube Data API v3 and redact query-string credentials from diagnostics and intermediary logs.
