/** * Pass: unrestricted-file-upload (CWE-434, category: security) * * Detects when an HTTP-uploaded file is saved to disk WITHOUT a filename * allow-list (extension check) or `secure_filename` normalization. * * Detection (per language): * * Java (Spring MultipartFile / Servlet Part): * - `file.transferTo(new File(dir, file.getOriginalFilename()))` * - `Files.copy(part.getInputStream(), Path.of(dir, part.getSubmittedFileName()))` * - `part.write(dir + part.getSubmittedFileName())` (Servlet 3.0 Part.write) * - Without preceding `ALLOWED_*.contains(ext)` or * `FilenameUtils.getExtension(name)` + check. * * JS/TS (multer / express-fileupload): * - `multer({ dest: '…' })` with NO `fileFilter` option. * - `fs.writeFile(path, req.file.buffer)` / `req.files.x.mv(path)` * without prior `path.extname` allow-list check. * * Python (Flask / Django / FastAPI): * - `f.save(os.path.join(UPLOAD_DIR, f.filename))` without prior * `secure_filename(f.filename)` wrapping. * * Go: * - `io.Copy(dst, file)` where `dst = os.Create(fileHeader.Filename)` * without an extension allow-list. * * The pass is intentionally conservative — it only fires when an upload-name * expression flows directly into a save sink in the same function and no * known allow-list / canonicalizer call appears earlier in the function. */ import type { AnalysisPass, PassContext } from '../../graph/analysis-pass.js'; export interface UnrestrictedFileUploadResult { findings: Array<{ line: number; api: string; language: string; }>; } export declare class UnrestrictedFileUploadPass implements AnalysisPass { readonly name = "unrestricted-file-upload"; readonly category: "security"; run(ctx: PassContext): UnrestrictedFileUploadResult; private emit; } //# sourceMappingURL=unrestricted-file-upload-pass.d.ts.map