T09 · Insecure Skill Coding Practices
- Location
scripts/query_by_user.py:103- Finding
Configurable API Base Can Exfiltrate the API Key in User Timeline Queries
- Content
View full analysis
Vulnerability Details
File Location:
scripts/query_by_user.py:22-29, 103-119
Vulnerability Type: Unrestricted credential destination and potentially plaintext credential transmission
Risk Level: MediumVulnerable Code
python def _request(url: str, api_key: str) -> dict: req = urllib.request.Request( url, headers={ "X-API-Key": api_key, "User-Agent": "twitter-query-skill/1.0", }, method="GET", )python api_key = os.environ.get("TWITTER_API_KEY", "").strip() if not api_key: print("Missing TWITTER_API_KEY", file=sys.stderr) sys.exit(1) base = os.environ.get("TWITTER_API_BASE", DEFAULT_BASE).rstrip("/") user = args.userName.lstrip("@") all_raw: list[dict] = [] cursor = "" pages = 0 meta_pages: list[dict] = [] while pages < args.max_pages: q = urllib.parse.urlencode( { "userName": user, "cursor": cursor, "includeReplies": "true" if args.include_replies else "false", } ) url = f"{base}/twitter/user/last_tweets?{q}" data = _request(url, api_key)Technical Analysis
The script accepts
TWITTER_API_BASEfrom the process environment without validating its URL scheme, hostname, port, or user-information component. It then attaches the sensitiveTWITTER_API_KEYvalue to the resulting request as anX-API-Keyheader.Consequently, an environment value such as
https://attacker.examplecauses the credential to be sent directly to an attacker-controlled server. Anhttp://endpoint can expose the credential and requested username to passive or active network attackers. Redirect behavior is delegated tourllib.request.urlopenwithout an explicit same-origin policy, creating an additional area where credential forwarding behavior should be hardened and tested.This behavior exceeds the disclosed destina ...[truncated 1455 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove
TWITTER_API_BASEconfigurability if custom endpoints are not essential and always usehttps://api.twitterapi.io. - If custom endpoints are required, parse the URL with
urllib.parse.urlsplitand enforce:- The
httpsscheme. - An explicit allowlist of trusted hostnames.
- No embedded username or password.
- Only approved ports, normally port 443.
- No fragments or other unexpected URL components.
- The
- Do not attach
X-API-Keyuntil the final request destination has passed validation. - Implement a redirect handler that rejects redirects or permits only same-origin HTTPS redirects to approved hosts.
- Fail closed when the URL is malformed or outside the allowlist.
- Update documentation and privacy metadata so that the declared destination rules exactly match implementation behavior.
- Add tests confirming rejection of
http://, look-alike domains, embedded credentials, unexpected ports, and cross-origin redirects.
- Remove
