chore(deps): upgrade file-type 16.5.4 -> 22.0.1 (clears the ASF-parser DoS)
file-type 16 -> 22 fixes GHSA-5v7r-6r5c-r473 (infinite loop in the ASF parser on
malformed input). v22 is ESM-only with a strict `exports` map, so the CommonJS
server can no longer `require()` it (and tsc would down-level a normal dynamic
import() back to require()). Converted the single call site in
nas-file-manager.ts to a cached runtime dynamic ESM import via the
Function('return import("file-type")') indirection (the same pattern server.ts
already uses for Vite), and updated the API to the v22 named export
`fileTypeFromBuffer` (was the v16 default `FileType.fromBuffer`).
Verified at runtime that the dynamic import loads v22 from CJS and detects
PNG/JPEG/PDF correctly. `npm audit` no longer lists file-type (6 -> 5 vulns; the
rest are quill [Phase 4] and Prisma 7's dev-tooling @hono/node-server).
Gates: tsc 0 | build 0 | vitest 247/247 | eslint 0 errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,25 @@ import path from "path";
|
||||
import { config } from "../config/env";
|
||||
import { localDateStr, localTimeStr } from "../utils/date";
|
||||
|
||||
const FileType = require("file-type") as typeof import("file-type");
|
||||
// file-type v22 is ESM-only. The server compiles to CommonJS, where a plain
|
||||
// `require("file-type")` fails (you can't require an ESM-only package) and tsc
|
||||
// would down-level a normal dynamic import() back to require(). The Function(...)
|
||||
// indirection keeps it a genuine runtime ESM import — the same trick server.ts
|
||||
// uses to load Vite from the CJS bundle. Cached so we import the module once.
|
||||
type FileTypeModule = {
|
||||
fileTypeFromBuffer: (
|
||||
buffer: Uint8Array,
|
||||
) => Promise<{ ext: string; mime: string } | undefined>;
|
||||
};
|
||||
let fileTypeModulePromise: Promise<FileTypeModule> | undefined;
|
||||
function loadFileType(): Promise<FileTypeModule> {
|
||||
if (!fileTypeModulePromise) {
|
||||
fileTypeModulePromise = Function(
|
||||
'return import("file-type")',
|
||||
)() as Promise<FileTypeModule>;
|
||||
}
|
||||
return fileTypeModulePromise;
|
||||
}
|
||||
|
||||
const BLOCKED_EXTENSIONS = new Set([
|
||||
"exe",
|
||||
@@ -378,8 +396,9 @@ export class NasFileManager {
|
||||
return "Tento typ souboru není povolen";
|
||||
}
|
||||
|
||||
// MIME validation
|
||||
const typeResult = await FileType.fromBuffer(fileBuffer);
|
||||
// MIME validation (file-type v22: named `fileTypeFromBuffer` export)
|
||||
const { fileTypeFromBuffer } = await loadFileType();
|
||||
const typeResult = await fileTypeFromBuffer(fileBuffer);
|
||||
if (typeResult) {
|
||||
if (this.isSuspiciousMime(typeResult.mime)) {
|
||||
return "Obsah souboru neodpovídá jeho příponě";
|
||||
|
||||
Reference in New Issue
Block a user