T09 · Insecure Skill Coding Practices
- Location
scripts/kb_tool.py:1460- Finding
Server-Side Request Forgery Through Unrestricted Note-Controlled URL Fetching
- Content
View full analysis
Dict[str, Any]: if not config.enable_network: return {"status": "failed", "url": url, "text": "", "error": "network disabled"} request = urllib.request.Request( url, headers={ "User-Agent": DEFAULT_USER_AGENT, "Accept": "text/html,application/xhtml+xml,text/plain,application/json;q=0.8,*/*;q=0.5", }, ) try: with urllib.request.urlopen(request, timeout=config.network_timeout) as response: raw = response.read(250000) ``` HTTP URLs extracted from notes become source candidates without destination validation: ```python def source_candidates_for_note(note: NormalizedNote, vault_root: pathlib.Path) -> List[Dict[str, str]]: candidates: List[Dict[str, str]] = [] seen = set() for link in dedupe_keep_order(([note.original_url] if note.original_url else []) + note.source_links): if not link or link in seen: continue seen.add(link) if link.startswith("obsidian://"): resolved = resolve_obsidian_uri_to_path(link, vault_root) if resolved: candidates.append({"kind": "obsidian_note", "value": str(resolved.resolve()), "raw": link}) else: candidates.append({"kind": "obsidian_note", "value": "", "raw": link}) elif link.startswith("http"): kind = "source_url" if link == note.original_url else "embedded_url" candidates.append({"kind": kind, "value": link, "raw": link}) return candidates ``` The resulting candidate is fetched ...[truncated 3881 chars]- Remediation
View remediation
