T09 · Insecure Skill Coding Practices
- Location
scripts/prompt_to_drawio.py:1093- Finding
Unrestricted URL ingestion permits SSRF and forwarding of retrieved data to an LLM provider
- Content
View full analysis
str: req = request.Request(url, headers={"User-Agent": "drawio-skill/1.0"}) try: with request.urlopen(req, timeout=timeout) as resp: charset = resp.headers.get_content_charset() or "utf-8" html = resp.read().decode(charset, errors="ignore") except Exception as exc: raise SkillRuntimeError(f"Failed to fetch URL {url}: {exc}") from exc parser = SimpleHTMLTextExtractor() parser.feed(html) text = parser.text.strip() if not text: raise SkillRuntimeError(f"URL had no extractable text: {url}") return text ``` ```python for url in urls: page_text = fetch_url_text(url) texts.append(f"[URL: {url}]\n{page_text}") ``` ```python bundle = read_context_bundle(args.file, args.url, args.shape_library) style_note = "Use minimal black/white styling." if args.minimal_style else "Use professional readable styling." user_text = compose_user_text(prompt, bundle, extra_sections=[style_note]) messages = build_messages(GENERATION_SYSTEM_PROMPT, user_text, bundle.image_data_urls) raw_xml = call_chat_completion( messages=messages, model=generation_model, api_key=api_key, base_url=args.base_url, temperature=args.temperature, max_tokens=args.max_tokens, timeout=args.timeout, ) ``` ### Technical Analysis The `--url` option accepts an arbitrary URL and passes it directly to `urllib.request.urlopen`. The implementation does not validate the URL scheme, resolve and inspect the destination address, restrict ports, reject local or private networks, or revalidate redirect destinations. The fetched response is converted to text, incorporated into the model prompt, and ...[truncated 1939 chars]- Remediation
View remediation
