File Type

Magic-byte content-type detection independent of the declared MIME. The Content-Type header on a multipart upload is supplied by the client; a hostile uploader can label a polyglot HTML payload as image/png and the header alone won't catch it. This primitive inspects the leading bytes against a hardcoded signature registry (PNG / JPEG / GIF / WEBP / AVIF / HEIC / PDF / OOXML / CFB / ZIP / RAR / 7Z / TAR / GZIP / BZ2 / XZ / MP3 / MP4 / WEBM / PE / ELF / Mach-O) and returns the actual format.

detect(buf) returns null rather than throwing on bad input (saved-for-later analysis often runs against partial reads); assertOneOf(buf, allowlist) throws FileTypeError when the detected format is not in the operator-supplied allowlist. Allowlist entries match against mime ("image/png"), short name ("png"), or category ("image") — operators pin the tightest level the use case allows.

Out of scope: content disarm (CDR), polyglot detection, and filename-extension validation. Operators with disarm requirements reach for a sandbox like dangerzone or vmray; filename extensions live behind b.guardFilename. Operators extending the registry pass opts.extra to detect — extras come first, letting an operator override a built-in entry without forking.

b.fileType.detect(buf, opts?) #

0.1.0
{
  extra: Array<{ name, mime, extension, category, offset, magic, extra? }>,
}

Inspects the leading bytes of buf against the signature registry and returns { mime, extension, category, name } for the first matching entry, or null when no signature matches (or buf is empty, or not a Buffer/Uint8Array). OOXML entries (docx/xlsx/ pptx) sit before generic ZIP so well-formed Office files win before the bare ZIP shape; operators extending the registry via opts.extra get their entries scanned first so they can override built-ins without forking.

var fs = require("node:fs");
var buf = fs.readFileSync("photo.png");
b.fileType.detect(buf);
// → { mime: "image/png", extension: "png", category: "image", name: "png" }

b.fileType.detect(Buffer.from(""));   // → null

b.fileType.assertOneOf(buf, allowlist, opts?) #

0.1.0
{
  allowEmpty: boolean,                                                // default false
  extra:      Array<{ name, mime, extension, category, offset, magic, extra? }>,
}

Detects the format of buf and throws FileTypeError when the result is not in allowlist. Allowlist entries match by mime ("image/png"), short name ("png"), or category ("image") so operators pin the tightest level the use case allows. A detected format outside the allowlist throws file-type/disallowed-type, naming what was detected. Unrecognized magic bytes throw file-type/unknown-type — the framework refuses to fall back to the advertised header MIME because the entire purpose of this primitive is mistrusting that header.

The call shape refuses with file-type/bad-input when buf is neither a Buffer nor a Uint8Array, file-type/empty for a zero-byte input unless opts.allowEmpty: true, and file-type/bad-opt when allowlist is not a non-empty array.

var fs = require("node:fs");
var buf = fs.readFileSync("photo.png");
var detected = b.fileType.assertOneOf(buf, ["image/png", "image/jpeg"]);
// → { mime: "image/png", extension: "png", category: "image", name: "png" }

// Category-level allowlist (any image format)
b.fileType.assertOneOf(buf, ["image"]);

b.fileType.extensionFor(mime) #

stable0.18.43

The canonical file extension for a MIME type, with no leading dot, or null when the framework does not recognize the type. Never a guess: a caller minting an object-store key or a Content-Disposition filename needs to know when the answer is unknown rather than receive a plausible-looking one.

detect answers "what is this"; the next question is usually "what should I call it", and the table that answers it is the same one. Reading it here rather than keeping a private copy is what stops the two drifting when a signature is added.

The lookup is case-insensitive and ignores content-type parameters, so the Content-Type header value a request arrived with can be passed straight in.

b.fileType.extensionFor("image/png");
// → "png"

b.fileType.mimeFor(extension) #

stable0.18.43

The MIME type for a file extension, or null when the framework does not recognize it. The inverse of b.fileType.extensionFor, over the same table.

A leading dot is accepted, because that is the form path.extname returns and therefore the form a caller usually has in hand. The lookup is case-insensitive.

This answers a naming question, not a trust question. It reports what an extension claims; it does not establish what a file IS. Only b.fileType.detect does that, by reading the bytes — an attacker controls the name, never the magic.

b.fileType.mimeFor(".png");
// → "image/png"

Last updated 2026-10-12T14:21:56.879Z by seeder.