T09 · Insecure Skill Coding Practices
- Location
fetch.js:12- Finding
Unbounded buffering of remote RSS responses
- Content
View full analysis
{ let data = ''; res2.on('data', chunk => data += chunk); res2.on('end', () => resolve(data)); }).on('error', reject); return; } let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => resolve(data)); ``` ### Technical Analysis The `fetchUrl` function accumulates the complete body of both direct and redirected HTTP responses in an in-memory string. It does not impose a maximum response size, configure a request timeout, or abort a response that continuously streams data. Because the response originates from an external service, the process cannot assume that its size or completion time is safe. A malicious, compromised, or malfunctioning feed server could return an extremely large response or maintain an indefinite chunked response. Repeated string concatenation can also increase memory and CPU consumption. ### Attack Path 1. An attacker compromises or gains control over one of the configured RSS endpoints, or its redirect destination. 2. The endpoint returns an extremely large response or continuously sends chunks without ending the response. 3. `fetchUrl` appends every chunk to the `data` string without enforcing a limit. 4. The Node.js process consumes increasing amounts of memory and CPU. 5. The process eventually becomes unresponsive, is terminated for exceeding its memory limit, or affects other workloads on the same host. ### Impact Assessment Successful exploitation can cause denial of service within the Node.js process. In resource-constrained or shared execution environments, excessive memory use may also degrade colocated workloads. This issue does not directly grant filesystem access, code execution, or additional operating-system priv ...[truncated 13 chars]- Remediation
View remediation
{ received += chunk.length; if (received > MAX_RESPONSE_BYTES) { res.destroy(new Error('RSS response exceeds the permitted size')); return; } chunks.push(chunk); }); res.on('end', () => { resolve(Buffer.concat(chunks).toString('utf8')); }); ``` ]]>
