secure-file-validator
Zero-dependency Node.js helper for upload type checks: extension, size, magic numbers, plus a small PDF and SVG content policy.
Aligned with the file-type checking part of OWASP Unrestricted File Upload and CWE-434. Not an antivirus. Not a complete upload-security stack.
Features
- Extension, size, and magic-number validation
- PDF name-token policy (including hex-escaped names and Flate streams)
- SVG policy for script,
javascript:, event handlers, and risky embeds - Path or buffer /
Uint8Arrayinput - Stable result codes for branching in app code
- Zero dependencies (Node.js 14.16+, ESM)
Installation
npm install secure-file-validator
Usage
Quick start
import { validateFile } from "secure-file-validator";
const result = await validateFile("uploads/photo.jpg");
if (result.ok) {
// result.code === "OK"
} else {
// result.code === "INVALID_SIGNATURE" | "PDF_JAVASCRIPT" | ...
console.error(result.code, result.message);
}
result.status still exists as a deprecated alias of result.ok.
From an upload buffer
import { validateFile, validateBytes } from "secure-file-validator";
const result = await validateFile(req.file.buffer, {
filename: req.file.originalname, // or extension: ".png"
});
if (!result.ok) {
throw new Error(result.code);
}
const sync = validateBytes(req.file.buffer, { extension: ".png" });
Buffer / Uint8Array input must include filename or extension. Size is checked with byteLength.
Supported types
| Extension | Magic check |
|---|---|
.jpg / .jpeg |
FF D8 FF |
.png |
89 50 4E 47 |
.gif |
47 49 46 38 |
.pdf |
%PDF + %%EOF, then token policy |
.svg |
<?xml or <svg, then SVG policy |
Default size cap: 5MB (options.maxSizeInBytes).
PDF policy
| Token | Default | code |
|---|---|---|
/Metadata |
allow | PDF_METADATA |
/Annots |
allow | PDF_ANNOTS |
/OpenAction |
allow | PDF_OPEN_ACTION |
/JS, /JavaScript |
deny | PDF_JAVASCRIPT |
/Launch |
deny | PDF_LAUNCH |
/EmbeddedFile |
deny | PDF_EMBEDDED_FILE |
/XFA |
deny | PDF_XFA |
/RichMedia |
deny | PDF_RICH_MEDIA |
const strict = await validateFile(pdfPath, {
pdf: { allowOpenAction: false },
});
// Dangerous: turns the script check off
const trusted = await validateFile(pdfPath, {
pdf: { allowJavaScript: true },
});
SVG policy
Always denied: <script>, javascript:, event handlers (onload= …), <!ENTITY.
Denied by default, overridable with options.svg:
| Rule | Default | code |
|---|---|---|
foreignObject |
deny | SVG_FOREIGN_OBJECT |
data: URI |
deny | SVG_DATA_URI |
external href |
deny | SVG_EXTERNAL_HREF |
await validateFile(svgPath, {
svg: { allowDataUri: true },
});
Result shape
{
ok: false,
status: false, // deprecated alias of ok
code: "PDF_JAVASCRIPT",
message: "Suspicious PDF name token detected: /JavaScript",
details: { token: "JavaScript" }
}
License
MIT
For more details, please visit the GitHub repository.