T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/milan-china-medals.js:64
- Finding
- Unbounded HTTP Response Buffering in China Medal Scraper## Vulnerability Details **File Location**: `scripts/milan-china-medals.js`, lines 64-71 **Vulnerability Type**: Uncontrolled memory allocation while buffering an HTTP response **Risk Level**: Medium **Vulnerable 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 `chunks` array and then allocates another contiguous buffer using `Buffer.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.concat` operation may temporarily increase memory pressure further because it creates a new allocation containing all collected chunks. ### Attack Path 1. The script requests the declared Baidu Sports medal endpoint over HTTPS. 2. The remote endpoint, or infrastructure controlling its response, returns an abnormally large body within the configured timeout. 3. Each response chunk is retained in the unbounded `chunks` array. 4. At response completion, `Buffer.concat(chunks)` attempts an additional allocation for the complete body. 5. 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
- ## Remediation Suggestions - Define a conservative maximum response size appropriate for the expected HTML payload. - Read and validate the `Content-Length` header when present, while still enforcing a streaming byte counter because that header may be absent or inaccurate. - Increment the byte counter in the `data` handler 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); }); ```
