T09 · Insecure Skill Coding Practices
- Location
scripts/worldcup-match.js:40- Finding
Unbounded Buffering of Remote HTTP Responses
- Content
View full analysis
Vulnerability Details
File Location:
scripts/worldcup-match.js:40-45
Vulnerability Type: Uncontrolled resource consumption through unbounded response buffering
Risk Level: MediumVulnerable Code
js const req = https.request(options, (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(chunk); }); res.on('end', () => { resolve(Buffer.concat(chunks).toString('utf-8')); }); });The same implementation pattern also appears in:
scripts/worldcup-player.js:40-45scripts/worldcup-rankings.js:50-60scripts/worldcup-rankings.js:82-87scripts/worldcup-schedule.js:30-35scripts/worldcup-team.js:44-49
Technical Analysis
The HTTP clients retain every received response chunk in an array and then create a second contiguous allocation with
Buffer.concat. They do not enforce a maximum response size, validate theContent-Lengthheader, or terminate a response after a byte threshold is exceeded.The configured 15-second request timeout does not provide an effective response-size limit. If an upstream server continuously sends data, the process can continue accumulating chunks until memory is exhausted. The final
Buffer.concatcan temporarily require approximately another allocation equal to the complete response size, increasing peak memory consumption.Exploitation requires control or compromise of a configured upstream service, or another condition causing that service to return an unexpectedly large response. The audited request URLs are otherwise constrained to the declared sports-data domains; no user-controlled host-based SSRF path was identified.
Attack Path
- An Agent invokes a documented command that retrieves data from Baidu Sports.
- The script establishes an HTTPS connection to the configured upstream endpoint.
- A compromised or malfunctioning upstream endpoint returns a very large response or continuously streams ...[truncated 877 chars]
- Remediation
View remediation
Remediation Suggestions
-
Enforce a conservative maximum response size and destroy the request immediately when the limit is exceeded:
js const MAX_RESPONSE_BYTES = 5 * 1024 * 1024; const req = https.request(options, (res) => { const declaredLength = Number(res.headers['content-length'] || 0); if (declaredLength > MAX_RESPONSE_BYTES) { res.destroy(); reject(new Error('Response exceeds the permitted size')); return; } const chunks = []; let receivedBytes = 0; res.on('data', (chunk) => { receivedBytes += chunk.length; if (receivedBytes > MAX_RESPONSE_BYTES) { res.destroy(); reject(new Error('Response exceeds the permitted size')); return; } chunks.push(chunk); }); res.on('end', () => { resolve(Buffer.concat(chunks, receivedBytes).toString('utf-8')); }); res.on('error', reject); }); -
Apply equivalent safeguards consistently to the HTTP helpers in:
scripts/worldcup-player.jsscripts/worldcup-rankings.jsscripts/worldcup-schedule.jsscripts/worldcup-team.js
-
Validate status codes before consuming response bodies and reject unexpected redirects or error responses.
-
Validate response media types, accepting only the expected HTML or JSON content types.
-
Use streaming parsers where practical so complete documents do not need to be retained in memory.
-
Configure Axios limits in
scripts/worldcup-calculator.js, includingmaxContentLength,maxBodyLength, and an explicit timeout. -
Add tests using oversized and indefinitely streaming mock responses to verify that requests are terminated and memory remains bounded.
-
