T09 · Insecure Skill Coding Practices
- Location
scripts/download_wiki.py:43- Finding
Authentication Token Forwarded to Untrusted Response-Provided URLs
- Content
View full analysis
Vulnerability Details
File Location:
scripts/download_wiki.py:43-45,scripts/download_wiki.py:65-70,scripts/download_wiki.py:93, andscripts/download_wiki.py:138-145
Vulnerability Type: Credential disclosure through unrestricted outbound requests
Risk Level: HighVulnerable Code
python def find_urls(value: Any) -> list[str]: urls: list[str] = [] if isinstance(value, dict): for item in value.values(): urls.extend(find_urls(item)) elif isinstance(value, list): for item in value: urls.extend(find_urls(item)) elif isinstance(value, str): if value.startswith(("https://", "http://")): urls.append(value) else: try: urls.extend(find_urls(json.loads(value))) except json.JSONDecodeError: pass return list(dict.fromkeys(urls))python def download(url: str, destination: Path, headers: dict[str, str]) -> None: with requests.get(url, headers=headers, stream=True, timeout=120) as response: response.raise_for_status() with destination.open("wb") as handle: for chunk in response.iter_content(chunk_size=1024 * 1024): if chunk: handle.write(chunk)python headers = {"X-Auth-Token": api_key(), "Content-Type": "application/json"}python urls = find_urls(result.get("result", result)) if not urls: raise RuntimeError("Task succeeded but no HTTP(S) download URL was found. Inspect provider_result.json.") for number, url in enumerate(urls, start=1): name = archive_name(url, number) archive = outdir / name download(url, archive, headers)Technical Analysis
The downloader recursively treats every HTTP or HTTPS string in the provider result as a package URL. It does not validate the destination against an allowli ...[truncated 1702 chars]
- Remediation
View remediation
Remediation Suggestions
- Require HTTPS for all package downloads and reject every
http://URL. - Maintain an explicit allowlist of expected SciMiner and object-storage hostnames.
- Use separate request headers:
- Include
X-Auth-Tokenonly for trusted SciMiner API endpoints. - Use a header-free request for signed storage URLs unless provider documentation explicitly requires authentication.
- Include
- Validate the scheme, hostname, port, and resolved final URL before downloading.
- Disable automatic redirects or validate every redirect target against the same allowlist.
- Replace recursive extraction of every URL with parsing of documented response fields.
- Avoid including
Content-Type: application/jsonin download requests where it is unnecessary. - Revoke and rotate any credential that may have been exposed through the current implementation.
- Add tests proving that unapproved hosts, HTTP URLs, and cross-host redirects are rejected and never receive the authentication header.
- Require HTTPS for all package downloads and reject every
