danny-avila/LibreChat · error

Invalid file path

Error message

Invalid file path

What it means

Thrown by deleteLocalFile when the filepath does not match the /uploads/{userId} pattern and isValidPath returns false. isValidPath resolves the filepath against publicPath/{subfolder}/{userId} and checks that the relative path stays inside. This guards non-upload files (e.g., /images/{userId}/...) against path traversal and cross-user deletion. The subfolder is extracted from the filepath's second path segment.

Source

Thrown at api/server/services/Files/Local/crud.js:267

    const rel = path.relative(userUploadDir, filepath);
    if (rel.startsWith('..') || path.isAbsolute(rel) || rel.includes(`..${path.sep}`)) {
      throw new Error(`Invalid file path: ${cleanFilepath}`);
    }

    await unlinkFile(filepath);
    return;
  }

  const parts = cleanFilepath.split(path.sep);
  const subfolder = parts[1];
  if (!subfolder && parts[0] === EModelEndpoint.agents) {
    logger.warn(`Agent File ${file.file_id} is missing filepath, may have been deleted already`);
    return;
  }
  const filepath = path.join(publicPath, cleanFilepath);

  if (!isValidPath(req, publicPath, subfolder, filepath)) {
    throw new Error('Invalid file path');
  }

  await unlinkFile(filepath);
};

/**
 * Uploads a file to the specified upload directory.
 *
 * @param {Object} params - The params object.
 * @param {ServerRequest} params.req - The request object from Express. It should have a `user` property with an `id` representing the user
 * @param {Express.Multer.File} params.file - The file object, which is part of the request. The file object should
 *                                     have a `path` property that points to the location of the uploaded file.
 * @param {string} params.file_id - The file ID.
 *
 * @returns {Promise<{ filepath: string, bytes: number }>}
 *          A promise that resolves to an object containing:
 *            - filepath: The path where the file is saved.
 *            - bytes: The size of the file in bytes.

View on GitHub (pinned to 5ff282f900)

Solutions

  1. Verify file.filepath in the database is a valid public path under the expected subfolder and user ID.
  2. Ensure the subfolder component matches a known public directory type (e.g., 'images').
  3. Audit the file creation pipeline to confirm filepath is always built as /{subfolder}/{userId}/{safeFilename}.
  4. Handle the error at the controller level and return 403 Forbidden, as this often indicates an authorization boundary violation.
Defensive patterns

Strategy: validation

Validate before calling

const cleanFilepath = file.filepath.split('?')[0];
const parts = cleanFilepath.split(path.sep);
const subfolder = parts[1];
if (!subfolder || !isValidPath(req, publicPath, subfolder, path.join(publicPath, cleanFilepath))) {
  throw new Error('File path validation failed');
}

Type guard

function isValidLocalFilePath(req, publicPath, filepath) {
  const clean = filepath.split('?')[0];
  const parts = clean.split(path.sep);
  const subfolder = parts[1];
  if (!subfolder) return false;
  return isValidPath(req, publicPath, subfolder, path.join(publicPath, clean));
}

Try / catch

try {
  await deleteLocalFile(req, file);
} catch (error) {
  if (error.message === 'Invalid file path') {
    return res.status(403).json({ error: 'File path is not within user scope' });
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling deleteLocalFile(req, file) where file.filepath references a public path (e.g., /images/{userId}/file.png) but the resolved path escapes the expected publicPath/subfolder/userId containment. This fires when isValidPath detects the filepath resolving outside the user's designated directory.

Common situations: A file record references a path under a different user's directory, or the subfolder does not match an expected image directory. Or an attacker crafts a filepath that resolves outside containment via traversal or absolute path injection. The subfolder extraction (parts[1]) can also be undefined if the filepath is a bare segment like '/images'.

Related errors


AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12). Data as JSON: /api/errors/090c8df0ee7482e5. Report an issue: GitHub.