T09 · Insecure Skill Coding Practices
Warning
- Location
- searchch.py:144
- Finding
- Unsanitized Remote Directory Data Allows Terminal and Markdown Output Injection<![CDATA[ ## Vulnerability Details **File Location**: `searchch.py:144-160`, `searchch.py:219-234` **Vulnerability Type**: Untrusted output injection through terminal and Markdown rendering **Risk Level**: Medium ### Vulnerable Code ```python # Extra fields (fax, email, website) for extra in entry.findall("tel:extra", NS): extra_type = extra.get("type", "") value = extra.text if value: value = value.rstrip("*") # Remove no-promo marker if extra_type == "fax": result["fax"] = format_phone(value) elif extra_type == "email": result["email"] = value elif extra_type == "website": # Parse "label: url" format if ": http" in value: result["website"] = value.split(": ", 1)[1] elif value.startswith("http"): result["website"] = value elif "website" not in result: result["website"] = value ``` ```python for i, r in enumerate(results, 1): # Name and type type_icon = "🏢" if r.get("type") == "Organisation" else "👤" print(f"{type_icon} **{r.get('name', 'Unbekannt')}**") # Occupation/subtitle if r.get("occupation"): print(f" {r['occupation']}") # Address addr_parts = [] if r.get("street"): addr_parts.append(r["street"]) if r.get("zip") or r.get("city"): addr_parts.append(f"{r.get('zip', '')} {r.get('city', '')}".strip()) if r.get("canton"): addr_parts[-1] = f"{addr_parts[-1]} {r['canton']}" if addr_parts else r["canton"] if addr_parts: print(f" 📍 {', '.join(addr_parts)}") # Contact - phone numbers with clickable tel: links if r.get("phone"): phone_display = format_phone(r['phone'], clickable=clickable) if clickable else r['phone'] print(f" 📞 {phone_display}") if r.get("fax"): fax_display = format_phone(r['fax'], clickable=clickable) if clickable else r['fax'] print(f" 📠 {f ...[truncated 3067 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove terminal control characters from every remotely sourced field.** Reject or strip ANSI escape sequences and nonprinting control characters before storing or displaying API values. 2. **Escape output for its rendering context.** When generating Markdown, escape characters such as `[`, `]`, `(`, `)`, backticks, asterisks, underscores, and backslashes in untrusted labels and text. 3. **Validate website URLs using a parsed scheme allowlist.** Use `urllib.parse.urlparse()` and accept only explicitly supported schemes, preferably `https` and optionally `http`. Do not treat arbitrary text as a website URL. 4. **Construct links from validated components.** Keep the escaped display label separate from the validated destination instead of accepting embedded Markdown from the API. 5. **Apply sanitization consistently.** Protect names, occupations, street addresses, cities, cantons, email addresses, websites, categories, and phone display values rather than correcting only the website field. 6. **Provide a plain-text-safe output mode.** If output is intended for terminals or downstream agents, default to literal text and require an explicit option to enable Markdown links. 7. **Add adversarial tests.** Test records containing ANSI escapes, carriage returns, newlines, Markdown links, nested formatting, deceptive Unicode, and unsupported URL schemes to ensure they are rendered harmlessly. ]]>
