T09 · Insecure Skill Coding Practices
- Location
scripts/ddg_search.js:12- Finding
Unbounded Network Response Buffering Can Cause Denial of Service
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ddg_search.js, lines 12–21 and 27–59
Vulnerability Type: Unbounded response buffering and missing network safeguards
Risk Level: MediumVulnerable Code
js function instantAnswer(query, cb) { const u = 'https://api.duckduckgo.com/?' + qs.stringify({ q: query, format: 'json', no_html: 1, no_redirect: 1 }); https.get(u, res => { let data = ''; res.on('data', c => data += c); res.on('end', () => { try { const j = JSON.parse(data); cb(null, j); } catch (e) { cb(e); } }); }).on('error', cb); } function serpFallback(query, cb) { const u = 'https://duckduckgo.com/html/?' + qs.stringify({ q: query }); https.get(u, res => { let data = ''; res.on('data', c => data += c); res.on('end', () => { try { const root = parse(data); const results = []; // DuckDuckGo HTML uses .result__a for links in modern markup; fallback scanning const anchors = root.querySelectorAll('a.result__a'); if (anchors.length === 0) { // older/simple HTML pages const items = root.querySelectorAll('.result'); for (const it of items.slice(0, 10)) { const a = it.querySelector('a'); if (!a) continue; const title = a.text.trim(); const url = a.getAttribute('href'); const snippetEl = it.querySelector('.result__snippet') || it.querySelector('.snippet') || null; const snippet = snippetEl ? snippetEl.text.trim() : ''; results.push({ title, url, snippet }); } } else { for (const a of anchors.slice(0, 10)) { const title = a.text.trim(); const url = a.getAttribute('href'); // try to find snippet nearby const parent = a.parentNode; let snippet ...[truncated 2118 chars]- Remediation
View remediation
Remediation Suggestions
- Enforce a strict maximum response size for both JSON and HTML responses. Track bytes as chunks arrive and immediately destroy the request when the limit is exceeded.
- Configure connection and overall response deadlines with
request.setTimeout()or anAbortController; destroy timed-out requests and return a controlled error. - Accept only successful HTTP status codes and explicitly handle or reject redirects.
- Validate the expected content type before buffering and parsing. Require JSON for the Instant Answer endpoint and an appropriate HTML media type for the SERP endpoint.
- Check
Content-Lengthwhen present, while retaining streaming byte enforcement because that header may be absent or inaccurate. - Avoid parsing responses after a size, timeout, status, or media-type violation.
- Add tests covering oversized responses, slow responses, incomplete bodies, invalid media types, malformed JSON or HTML, and non-2xx status codes.
- Consider issuing the HTML request only when the Instant Answer response is insufficient, reducing unnecessary exposure and resource consumption.
