T09 · Insecure Skill Coding Practices
- Location
scripts/mdnew.py:5- Finding
Complete User-Supplied URL Disclosed to a Third-Party Conversion Service
- Content
View full analysis
Vulnerability Details
File Location:
scripts/mdnew.py:5-14
Vulnerability Type: Sensitive data exposure through unrestricted URL forwarding
Risk Level: MediumVulnerable Code
python def fetch_markdown(url): # Construct the markdown.new URL md_new_url = f"https://markdown.new/{url}" # Request headers to match the tool's optimized behavior headers = { "Accept": "text/markdown, text/html", "User-Agent": "OpenClaw-MDNew-Skill/1.0" } try: req = urllib.request.Request(md_new_url, headers=headers)Technical Analysis
The script inserts the complete user-supplied URL into a request sent to the external
markdown.newservice. Although using that service is consistent with the functionality declared inSKILL.md, the implementation does not validate or sanitize the URL before disclosure.Consequently, all URL components may be transmitted to the third party, including:
- Usernames and passwords in the authority component.
- API keys, session identifiers, and signed-access parameters in the query string.
- Confidential hostnames, paths, filenames, and resource identifiers.
- URLs referring to private, loopback, link-local, or cloud metadata destinations.
The script accepts an arbitrary command-line string and does not restrict it to valid public HTTP or HTTPS resources. It also does not warn users that credentials and query parameters will leave the target origin. This exceeds the minimum safe privilege required for public-page conversion because authenticated and confidential URLs are treated identically to public URLs.
This is not covert exfiltration: the documentation expressly states that
markdown.newperforms the conversion. The security issue is the absence of controls preventing accidental transmission of sensitive URL data.Attack Path
- An attacker, untrusted document, or external instruction supplies a URL containing sensitive data, such as `https://example ...[truncated 1318 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse input with
urllib.parse.urlsplitand permit only explicithttpandhttpsschemes. - Reject URLs containing username or password fields.
- Detect query strings and require explicit confirmation before sending them to the external service; reject known credential-like parameters by default.
- Remove fragments because they are unnecessary for ordinary server-side retrieval and may contain sensitive state.
- Resolve destination hostnames and reject loopback, private, link-local, reserved, and cloud metadata address ranges where practical.
- Clearly disclose before execution that the complete target URL will be sent to
markdown.new. - Prefer direct retrieval and local Markdown conversion for authenticated, signed, internal, or otherwise confidential resources.
- Use the service's documented parameter-encoding mechanism rather than unvalidated raw string concatenation.
- Add automated tests covering embedded credentials, query tokens, malformed URLs, non-HTTP schemes, localhost, private IP addresses, and metadata endpoints.
- Parse input with
