T09 · Insecure Skill Coding Practices
- Location
scripts/milan-china-medals.js:64- Finding
Unbounded HTTP Response Buffering in China Medal Scraper
- Content
View full analysis
Vulnerability Details
File Location:
scripts/milan-china-medals.js, lines 64-71
Vulnerability Type: Uncontrolled memory allocation while buffering an HTTP response
Risk Level: MediumVulnerable Code:
js const req = https.request(options, (res) => { const chunks = []; res.on('data', (chunk) => { chunks.push(chunk); }); res.on('end', () => { const buffer = Buffer.concat(chunks); resolve(buffer.toString('utf-8')); }); });Technical Analysis
The HTTP client stores every response chunk in the
chunksarray and then allocates another contiguous buffer usingBuffer.concat. It does not enforce a maximum response size before or during buffering.The 15-second request timeout elsewhere in the function limits elapsed time, but it does not limit the number of bytes that may be delivered during that interval. A compromised upstream service, malicious intermediary capable of controlling the trusted response, or unexpectedly large legitimate response could therefore cause excessive memory consumption. The final
Buffer.concatoperation may temporarily increase memory pressure further because it creates a new allocation containing all collected chunks.Attack Path
- The script requests the declared Baidu Sports medal endpoint over HTTPS.
- The remote endpoint, or infrastructure controlling its response, returns an abnormally large body within the configured timeout.
- Each response chunk is retained in the unbounded
chunksarray. - At response completion,
Buffer.concat(chunks)attempts an additional allocation for the complete body. - The Node.js process experiences excessive memory consumption and may be terminated or crash with an out-of-memory error.
Exploitation requires influence over the remote response or network infrastructure trusted by the process; the URL is fixed and is not directly supplied by a local user.
Impact Assessment
T ...[truncated 367 chars]
- Remediation
View remediation
Remediation Suggestions
- Define a conservative maximum response size appropriate for the expected HTML payload.
- Read and validate the
Content-Lengthheader when present, while still enforcing a streaming byte counter because that header may be absent or inaccurate. - Increment the byte counter in the
datahandler and destroy the response immediately if the limit is exceeded. - Validate the HTTP status code and expected content type before buffering the body.
- Prefer a streaming parser where practical.
- Ensure that overflow and aborted-response conditions reject the promise exactly once.
Example hardening pattern:
js const MAX_RESPONSE_BYTES = 5 * 1024 * 1024; const req = https.request(options, (res) => { if (res.statusCode !== 200) { res.resume(); reject(new Error(`Unexpected HTTP status: ${res.statusCode}`)); return; } let received = 0; const chunks = []; res.on('data', (chunk) => { received += chunk.length; if (received > MAX_RESPONSE_BYTES) { res.destroy(new Error('Response exceeds size limit')); return; } chunks.push(chunk); }); res.on('end', () => { resolve(Buffer.concat(chunks, received).toString('utf-8')); }); res.on('error', reject); });
