T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/used_price_compare/fetcher.py:20
- Finding
- Weak Marketplace Hostname Validation Allows Navigation to Attacker-Controlled Origins<![CDATA[ ## Vulnerability Details **File Location**: `scripts/used_price_compare/fetcher.py:20-46`; request sink in `adapters/ebay/detail.js:17` and equivalent detail adapters **Vulnerability Type**: Insufficient URL validation and arbitrary browser navigation **Risk Level**: High ### Vulnerable Code ```python _PLATFORM_RULES: list[tuple[str, str, str]] = [ # (domain pattern, adapter name, platform label) (r"\.ok\.com$", "ok/detail", "ok.com"), (r"\.ebay\.", "ebay/detail", "ebay"), (r"\.gumtree\.com$", "gumtree/detail", "gumtree"), (r"\.amazon\.", "amazon/detail", "amazon"), ] def resolve_adapter(url: str) -> tuple[str, str] | None: """Determine which bb-browser adapter to use for a given URL.""" try: host = urlparse(url).hostname or "" except Exception: return None for pattern, adapter, label in _PLATFORM_RULES: if re.search(pattern, host): return adapter, label return None ``` The accepted URL is subsequently passed unchanged to an adapter: ```javascript async function(args) { if (!args.url) return { error: 'Missing argument: url' }; const resp = await fetch(args.url, { credentials: 'include' }); if (!resp.ok) return { error: `HTTP ${resp.status}`, hint: 'Check if the listing URL is valid' }; ``` ### Technical Analysis The eBay and Amazon patterns are substring checks rather than registrable-domain checks. A hostname such as `shop.ebay.attacker.example` contains `.ebay.` and is therefore accepted as eBay, despite being controlled by an attacker. The same weakness applies to names containing `.amazon.`. The accepted URL is opened in the bb-browser context with `credentials: 'include'`. Browser cookie scoping should ordinarily prevent actual eBay or Amazon cookies from being attached to an unrelated attacker domain, so direct cross-domain cookie theft is not established. Nevertheless, this permits an attacker to make the Skill navigate its browser context to an arbitrar ...[truncated 1304 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Require `https` explicitly and reject URLs containing usernames, passwords, malformed ports, or unsupported schemes. 2. Replace substring regular expressions with exact registrable-domain allowlists. 3. Accept a host only when it is exactly an approved domain or ends with `"." + approved_domain`. 4. Maintain explicit regional allowlists, for example: - `ebay.com`, `ebay.co.uk`, `ebay.com.au`, `ebay.ca` - `amazon.com`, `amazon.co.uk` - approved Gumtree and OK.com domains 5. Normalize hostnames using IDNA before comparison and reject ambiguous or invalid hostnames. 6. Revalidate the destination after every redirect. 7. Avoid `credentials: 'include'` unless authenticated marketplace access is necessary. Prefer `credentials: 'omit'` for public listing pages. 8. Add negative tests for hosts such as `ebay.attacker.example`, `amazon.evil.example`, and `ebay.com.attacker.example`. ]]>
