T09 · Insecure Skill Coding Practices
- Location
scripts/discover_apis.js:15- Finding
Overbroad hostname matching exposes unrelated cross-origin request URLs
- Content
View full analysis
e.name.includes(hostname)) .filter(e => !e.name.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|ico|woff|woff2|ttf|eot)(\?|$)/)); ``` The same pattern is prescribed in `SKILL.md:35-37`: ```javascript const entries = performance.getEntriesByType('resource') .filter(e => e.name.includes(window.location.hostname) && !e.name.match(/\.(js|css|png|jpg|webp|svg|woff|ttf)(\?|$)/)) ``` ### Technical Analysis The code claims to select resources from the same domain, but it uses substring matching against the complete URL. This does not verify the parsed URL's hostname or origin. For example, if the current hostname is `target.example`, all of the following can satisfy the check: ```text https://target.example.attacker.test/api https://attacker.test/path?source=target.example https://attacker.test/target.example/api ``` The script subsequently parses accepted entries and returns their paths, including query strings: ```javascript const url = new URL(e.name); const path = url.pathname + url.search; ``` Query parameters may contain signed URL values, access identifiers, personal data, search terms, or session-like secrets. Although paths are truncated to 200 characters in the script, truncation is not redaction and does not reliably prevent disclosure. This behavior exceeds the minimum privilege necessary for same-origin API discovery because unrelated cross-origin resources are included even though the declared functionality only requires discovering APIs associated with the target application. ### Attack Path 1. A user opens a maliciou ...[truncated 1310 chars]- Remediation
View remediation
{ try { return new URL(entry.name).origin === currentOrigin; } catch { return false; } }) .filter(entry => !new URL(entry.name).pathname.match( /\.(js|css|png|jpg|jpeg|gif|webp|svg|ico|woff|woff2|ttf|eot)$/i ) ); ``` 2. If trusted subdomains are required, use an explicit hostname allowlist rather than suffix or substring matching. 3. Do not return complete query strings by default. Return the origin and pathname, together with parameter names but not parameter values: ```javascript const url = new URL(entry.name); const safeEntry = { origin: url.origin, path: url.pathname, queryParameters: [...url.searchParams.keys()] }; ``` 4. Explicitly redact sensitive parameter names such as `token`, `key`, `secret`, `signature`, `auth`, `session`, and `code`. 5. Require confirmation before testing any endpoint outside the exact origin of the page. 6. Apply the same correction to both the executable script and the workflow example in `SKILL.md` so users are not instructed to reproduce the vulnerable pattern. ]]>
