Mintplex-Labs/anything-llm · error · Error
Invalid file path.
Error message
Invalid file path.
What it means
Thrown by renameLogoFile() when the uploaded logo's originalFilename, after normalizePath, resolves outside the assets directory. It is the path-traversal guard for the logo-upload pipeline: the original name is user-controlled (multer filename), so an attacker-supplied name carrying '..' or an absolute prefix is refused before fs.renameSync runs. The output filename is always a random uuid, so only the input side needs this check.
Source
Thrown at server/utils/files/logo.js:84
found: true,
buffer,
size: buffer.length,
mime,
};
}
async function renameLogoFile(originalFilename = null) {
const extname = path.extname(originalFilename) || ".png";
const newFilename = `${v4()}${extname}`;
const assetsDirectory = process.env.STORAGE_DIR
? path.join(process.env.STORAGE_DIR, "assets")
: path.join(__dirname, `../../storage/assets`);
const originalFilepath = path.join(
assetsDirectory,
normalizePath(originalFilename)
);
if (!isWithin(path.resolve(assetsDirectory), path.resolve(originalFilepath)))
throw new Error("Invalid file path.");
// The output always uses a random filename.
const outputFilepath = process.env.STORAGE_DIR
? path.join(process.env.STORAGE_DIR, "assets", normalizePath(newFilename))
: path.join(__dirname, `../../storage/assets`, normalizePath(newFilename));
fs.renameSync(originalFilepath, outputFilepath);
return newFilename;
}
async function removeCustomLogo(logoFilename = LOGO_FILENAME) {
if (!logoFilename || !validFilename(logoFilename)) return false;
const assetsDirectory = process.env.STORAGE_DIR
? path.join(process.env.STORAGE_DIR, "assets")
: path.join(__dirname, `../../storage/assets`);
const logoPath = path.join(assetsDirectory, normalizePath(logoFilename));
if (!isWithin(path.resolve(assetsDirectory), path.resolve(logoPath)))View on GitHub (pinned to 526360e320)
Solutions
- At the upload handler, strip the filename to its basename (path.basename) before passing to renameLogoFile.
- Reject filenames containing path separators or '..' at the multer filename resolver.
- Treat the thrown error as 400 and log the rejected filename for audit.
- Prefer letting the server generate the filename entirely and ignore the client-supplied original.
Example fix
// before const newFile = await renameLogoFile(originalFilename); // originalFilename may be '../x.png' // after const safeName = path.basename(originalFilename || 'logo.png'); const newFile = await renameLogoFile(safeName);
Defensive patterns
Strategy: validation
Validate before calling
const safeName = path.basename(originalFilename || 'logo.png');
if (safeName.includes('..')) throw new UserError('Invalid filename', 400); Type guard
function isBasenameOnly(v): v is string {
return typeof v === 'string' && v === path.basename(v) && !v.includes('..');
} Try / catch
try {
await renameLogoFile(path.basename(originalFilename));
} catch (e) {
if (e.message === 'Invalid file path.') return res.status(400).json({ error: e.message });
throw e;
} Prevention
- Strip uploaded filenames to basename at the multer filename resolver.
- Reject filenames containing '..' or separators before they reach storage.
- Prefer server-generated filenames and ignore the client-supplied original.
When it happens
Trigger: A logo upload whose filename is '../../../etc/passwd', an absolute path like '/x.png', or contains backslash traversal on Windows. Reaching the guard means normalizePath did not fully neutralize the payload.
Common situations: A penetration test against the logo upload endpoint; a buggy client that sends the full local filesystem path as the filename header; charset-corrupted filenames from the upload pipeline.
Related errors
AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13).
Data as JSON: /api/errors/5f74606bc31d663c.
Report an issue: GitHub.