checkUploadSize middleware never rejects oversized uploads
checkUploadSize only triggers a challenge marker when a file exceeds 100 KB but always calls next(), so there is no actual server-side size enforcement on file uploads.
The middleware that is named like a size guard does not enforce any limit:
function checkUploadSize ({ file }: Request, res: Response, next: NextFunction) {
if (file != null) {
challengeUtils.solveIf(challenges.uploadSizeChallenge, () => { return file?.size > 100000 })
}
next()
}
solveIf only marks a CTF challenge as solved; control flow still falls through to next() regardless of the file size. There is no limits.fileSize configured on multer here, no early res.status(413) branch, and no per-request size cap. Combined with the downstream parsers (libxml.parseXml, yaml.load, unzipper.Parse) being invoked on the same buffer, an attacker can submit arbitrarily large files (or YAML/ZIP bombs) that will be buffered in memory and parsed.
curl -X POST http://target/file-upload -F 'file=@huge.bin' where huge.bin is several GB; the request is accepted and checkUploadSize lets it flow into the parser stack, leading to memory exhaustion / DoS. A 50 MB YAML bomb sent as bomb.yml is buffered, decoded with file.buffer.toString() and passed to yaml.load inside a vm context.
Unauthenticated denial of service: attackers can fill memory or stall the event loop by uploading arbitrarily large files or parser bombs. Because the same endpoint also feeds an XXE-enabled XML parser and a Zip extractor, oversized inputs amplify those parser-side bugs as well.
The checkUploadSize function on lines 61–66 only calls challengeUtils.solveIf(...) to mark a CTF challenge as solved when file.size > 100000, then unconditionally calls next(). There is no res.status(413), no early return, and no multer limits.fileSize set in this file. The buffered file then flows into handleXmlUpload/handleYamlUpload which invoke libxml.parseXml, yaml.load, and unzipper.Parse on the entire buffer, making memory-exhaustion / parser-bomb DoS reachable from an unauthenticated POST. Per the scope rules, the training-app context cannot downgrade this — the middleware named like a size guard demonstrably fails to enforce a size limit.
The checkUploadSize middleware only calls challengeUtils.solveIf and then unconditionally invokes next(), with no limits.fileSize on multer and no 413 branch, so arbitrarily large uploads reach the HTTP endpoint remotely without authentication (AV:N, PR:N, UI:N, AC:L). The downstream handlers buffer the entire file in memory and feed it to libxml.parseXml, yaml.load, and unzipper.Parse, so a multi-GB upload or a YAML/ZIP bomb causes memory exhaustion and event-loop stalls — a clear high-availability impact (A:H). The bug itself doesn't leak data or let the attacker modify state (C:N, I:N), and the DoS stays within the Node.js process boundary (S:U).
- CWE-400
- CWE-770
- OWASP A04:2021 - Insecure Design