{"record":{"id":"5f74606bc31d663c","repo":"Mintplex-Labs/anything-llm","slug":"invalid-file-path","errorCode":null,"errorMessage":"Invalid file path.","messagePattern":"Invalid file path\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/files/logo.js","lineNumber":84,"sourceCode":"    found: true,\n    buffer,\n    size: buffer.length,\n    mime,\n  };\n}\n\nasync function renameLogoFile(originalFilename = null) {\n  const extname = path.extname(originalFilename) || \".png\";\n  const newFilename = `${v4()}${extname}`;\n  const assetsDirectory = process.env.STORAGE_DIR\n    ? path.join(process.env.STORAGE_DIR, \"assets\")\n    : path.join(__dirname, `../../storage/assets`);\n  const originalFilepath = path.join(\n    assetsDirectory,\n    normalizePath(originalFilename)\n  );\n  if (!isWithin(path.resolve(assetsDirectory), path.resolve(originalFilepath)))\n    throw new Error(\"Invalid file path.\");\n\n  // The output always uses a random filename.\n  const outputFilepath = process.env.STORAGE_DIR\n    ? path.join(process.env.STORAGE_DIR, \"assets\", normalizePath(newFilename))\n    : path.join(__dirname, `../../storage/assets`, normalizePath(newFilename));\n\n  fs.renameSync(originalFilepath, outputFilepath);\n  return newFilename;\n}\n\nasync function removeCustomLogo(logoFilename = LOGO_FILENAME) {\n  if (!logoFilename || !validFilename(logoFilename)) return false;\n  const assetsDirectory = process.env.STORAGE_DIR\n    ? path.join(process.env.STORAGE_DIR, \"assets\")\n    : path.join(__dirname, `../../storage/assets`);\n\n  const logoPath = path.join(assetsDirectory, normalizePath(logoFilename));\n  if (!isWithin(path.resolve(assetsDirectory), path.resolve(logoPath)))","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/files/logo.js#L66-L102","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nconst newFile = await renameLogoFile(originalFilename); // originalFilename may be '../x.png'\n\n// after\nconst safeName = path.basename(originalFilename || 'logo.png');\nconst newFile = await renameLogoFile(safeName);","handlingStrategy":"validation","validationCode":"const safeName = path.basename(originalFilename || 'logo.png');\nif (safeName.includes('..')) throw new UserError('Invalid filename', 400);","typeGuard":"function isBasenameOnly(v): v is string {\n  return typeof v === 'string' && v === path.basename(v) && !v.includes('..');\n}","tryCatchPattern":"try {\n  await renameLogoFile(path.basename(originalFilename));\n} catch (e) {\n  if (e.message === 'Invalid file path.') return res.status(400).json({ error: e.message });\n  throw e;\n}","preventionTips":["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."],"tags":["path-traversal","security","filesystem","upload","branding"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}