T09 · Insecure Skill Coding Practices
- Location
url2pdf.py:93- Finding
Unrestricted Browser Navigation Enables Server-Side Request Forgery and Local Resource Disclosure
- Content
View full analysis
Vulnerability Details
File Location:
url2pdf.py, lines 93-106
Vulnerability Type: Unrestricted URL navigation / SSRF
Risk Level: HighThe application accepts an arbitrary URL, directs a Chromium browser to navigate to it, converts the resulting page into a PDF, and exposes the PDF path for delivery to the requesting user.
python def main(): args = cli() url = args.url pdf_path = get_pdf_path(url, output=args.output) device = iPhone13Pro() with sync_playwright() as p: browser = p.chromium.launch() context = device.get_context(browser) page = context.new_page() try: page.goto(url, wait_until="domcontentloaded", timeout=30000) # Give it a small buffer for fonts/images to settle page.wait_for_timeout(3000) except Exception as e: print(f"Navigation warning: {e}") print("Proceeding to print...") device.save_as_pdf(page, pdf_path) print(pdf_path) browser.close()The related instructions in
SKILL.md, lines 35-45, direct the Agent to return the generated file:markdown ### Agent Instructions 1. **Run the script**: Pass the url to be converted as an argument. 2. **Handle Output**: The script will output a path to a pdf file. Use the `message` tool to send the pdf file to the user as a document message: ```json { "action": "send", "filePath": "<filepath>" }text ### Technical Analysis The value supplied through the positional `url` argument is passed directly to `page.goto()` without validating its scheme, destination hostname, resolved IP addresses, port, or redirect chain. Consequently, the browser can be directed toward resources accessible from the Agent host but not from the external user. Potential targets include: - Loopback services such as `http://127.0.0.1:PORT/` - Private-network s ...[truncated 2312 chars]- Remediation
View remediation
Remediation Suggestions
- Permit only explicitly supported schemes, preferably
httpsand, where necessary,http. - Reject
file:,data:,javascript:,ftp:, and all other non-approved schemes. - Reject URLs containing embedded credentials.
- Resolve the destination hostname before navigation and reject every resolved address belonging to loopback, private, link-local, multicast, unspecified, reserved, or metadata-related ranges for both IPv4 and IPv6.
- Revalidate the destination after every redirect and terminate navigation before Chromium connects to a prohibited address.
- Defend against DNS rebinding by ensuring the address Chromium connects to is the validated address, or by enforcing destination restrictions at a network proxy or firewall.
- Run Chromium in an isolated container or sandbox with no access to host files and with tightly restricted outbound network access.
- Block access to cloud metadata addresses at the operating-system, container, or network layer.
- Apply an explicit hostname allowlist if the Skill only needs to support known public websites.
- Record rejected destinations without logging URL credentials or other sensitive query data.
- Add tests covering loopback, RFC 1918 ranges, IPv6, encoded addresses, redirect-to-private-host cases, DNS rebinding scenarios, and prohibited schemes.
- Permit only explicitly supported schemes, preferably
