T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/main.py:271
- Finding
- Server-Side Request Forgery Through Unrestricted External Link Validation## Vulnerability Details **File Location**: `scripts/main.py`, lines 271–277 **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: Medium ### Vulnerable Code ```python url_pattern = r'\[.*?\]\((https?://[^\s)]+)\)' for i, line in enumerate(lines): for match in re.finditer(url_pattern, line): url = match.group(1) col = match.start(1) try: response = requests.head(url, timeout=5, allow_redirects=True) ``` ### Technical Analysis When external link checking is enabled, the linter extracts HTTP and HTTPS URLs directly from the contents of a Markdown file and sends a `HEAD` request to each URL. The destination is not checked against an allowlist, nor are resolved addresses rejected when they belong to loopback, private, link-local, reserved, or cloud metadata ranges. Because `allow_redirects=True` is enabled, checking only the initial URL would also be insufficient: an attacker-controlled public endpoint could redirect the request to an internal address. Each redirect destination and its resolved addresses must be validated. Although the request uses the `HEAD` method and does not normally download a response body, this does not eliminate SSRF. The operation can still reveal endpoint reachability and status codes, interact with services that process `HEAD`, or trigger behavior in endpoints that do not implement HTTP method semantics safely. The vulnerable functionality is optional and is reached when the user invokes the documented `--check-external-links` option. ### Attack Path 1. An attacker creates or modifies a Markdown file that will be linted. 2. The attacker embeds a link targeting a sensitive destination, such as a loopback service, a private-network host, a link-local metadata endpoint, or a public URL that redirects to one: ```markdown [Internal probe](http://127.0.0.1:8080/admin) ``` 3. A user or automated process runs the linter with external link validation enabled: ` ...[truncated 1455 chars]
- Remediation
- ## Remediation Suggestions 1. Resolve destination hostnames before making requests and reject every address in loopback, private, link-local, multicast, reserved, unspecified, and other non-public ranges for both IPv4 and IPv6. 2. Explicitly block known infrastructure metadata destinations, including link-local metadata addresses and provider-specific metadata hostnames. 3. Disable automatic redirects by default. If redirects are required, validate the scheme, hostname, port, and all resolved IP addresses at every redirect hop. 4. Permit only `http` and `https`, reject embedded credentials, and restrict destination ports to an approved set such as 80 and 443. 5. Prefer an explicit hostname allowlist when the expected link destinations are known. 6. Protect against DNS rebinding by connecting only to the validated resolved address while preserving safe hostname verification for HTTPS. 7. Apply strict connection and total-request timeouts, redirect limits, URL-count limits, and concurrency limits to reduce network resource exhaustion. 8. Run external-link checking in a sandbox with restricted outbound network access and no access to sensitive internal networks. 9. Keep external validation disabled by default and clearly warn that it must not be enabled for untrusted Markdown unless network isolation is in place. 10. Add automated tests covering loopback, RFC 1918 private ranges, IPv6 local ranges, link-local addresses, unusual IP representations, DNS rebinding scenarios, and public-to-private redirects.
