T09 · Insecure Skill Coding Practices
- Location
scripts/generate_report.py:215- Finding
Unvalidated URL Scheme Allows Dangerous Links in Generated Reports
- Content
View full analysis
{e(pno)}' if url else e(pno) ``` ### Technical Analysis The `e()` function applies HTML escaping, which prevents an attacker from terminating the `href` attribute and injecting arbitrary HTML attributes or elements. However, HTML escaping does not validate the URL scheme. Consequently, attacker-controlled schemes such as the following can remain valid link destinations: ```text javascript:alert(document.domain) data:text/html, ``` The vulnerable value can originate from patent search results or directly supplied report-generation JSON. The search-processing code preserves the `url` field without checking its scheme or destination, and the report generator later treats every nonempty value as a trusted external link. When a reviewer clicks the generated patent-number link, browser-dependent script execution, navigation to attacker-controlled content, phishing, or unintended network access may occur. The generated report does not add a Content Security Policy that could provide defense in depth against dangerous navigation. ### Attack Path 1. An attacker controls or contaminates a patent-search result, intermediate verification JSON file, or other input consumed by the report generator. 2. The attacker assigns a dangerous value to a patent record's `url`, for example: ```json { "patent_no": "CN123456", "title": "Example Patent", "url": "javascript:alert(docu ...[truncated 1473 chars]- Remediation
View remediation
str | None: candidate = str(value or "").strip() if not candidate: return None try: parsed = urlsplit(candidate) except ValueError: return None if parsed.scheme.lower() != "https": return None hostname = (parsed.hostname or "").lower() if hostname not in APPROVED_PATENT_HOSTS: return None return candidate ``` Use the validator before generating the link: ```python url = safe_patent_url(item.get("url")) if url: pno_cell = ( f'{e(pno)}' ) else: pno_cell = e(pno) ``` The same validation should be applied when patent results first enter the verification pipeline so unsafe values are not propagated to other consumers. ]]>
