repatch path normalization (#1516)

This commit is contained in:
Timothy Carambat 2024-05-23 14:52:04 -05:00 committed by GitHub
parent 05488c81e0
commit a89812703b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 59 additions and 39 deletions

View File

@ -49,9 +49,9 @@ function writeToServerDocuments(
const destination = destinationOverride
? path.resolve(destinationOverride)
: path.resolve(
__dirname,
"../../../server/storage/documents/custom-documents"
);
__dirname,
"../../../server/storage/documents/custom-documents"
);
if (!fs.existsSync(destination))
fs.mkdirSync(destination, { recursive: true });
const destinationFilePath = path.resolve(destination, filename) + ".json";
@ -82,7 +82,7 @@ async function wipeCollectorStorage() {
if (file === "__HOTDIR__.md") continue;
try {
fs.rmSync(path.join(directory, file));
} catch { }
} catch {}
}
resolve();
});
@ -97,7 +97,7 @@ async function wipeCollectorStorage() {
if (file === ".placeholder") continue;
try {
fs.rmSync(path.join(directory, file));
} catch { }
} catch {}
}
resolve();
});

View File

@ -5,6 +5,7 @@ const {
viewLocalFiles,
findDocumentInDocuments,
normalizePath,
isWithin,
} = require("../../../utils/files");
const { reqBody } = require("../../../utils/http");
const { EventLogs } = require("../../../models/eventLogs");
@ -603,6 +604,8 @@ function apiDocumentEndpoints(app) {
try {
const { name } = reqBody(request);
const storagePath = path.join(documentsPath, normalizePath(name));
if (!isWithin(path.resolve(documentsPath), path.resolve(storagePath)))
throw new Error("Invalid path name");
if (fs.existsSync(storagePath)) {
response.status(500).json({

View File

@ -1,5 +1,5 @@
const { Document } = require("../models/documents");
const { normalizePath, documentsPath } = require("../utils/files");
const { normalizePath, documentsPath, isWithin } = require("../utils/files");
const { reqBody } = require("../utils/http");
const {
flexUserRoleValid,
@ -18,6 +18,8 @@ function documentEndpoints(app) {
try {
const { name } = reqBody(request);
const storagePath = path.join(documentsPath, normalizePath(name));
if (!isWithin(path.resolve(documentsPath), path.resolve(storagePath)))
throw new Error("Invalid folder name.");
if (fs.existsSync(storagePath)) {
response.status(500).json({

View File

@ -1,7 +1,7 @@
process.env.NODE_ENV === "development"
? require("dotenv").config({ path: `.env.${process.env.NODE_ENV}` })
: require("dotenv").config();
const { viewLocalFiles, normalizePath } = require("../utils/files");
const { viewLocalFiles, normalizePath, isWithin } = require("../utils/files");
const { purgeDocument, purgeFolder } = require("../utils/files/purgeDocument");
const { getVectorDbClass } = require("../utils/helpers");
const { updateENV, dumpENV } = require("../utils/helpers/updateENV");
@ -622,11 +622,13 @@ function systemEndpoints(app) {
const userRecord = await User.get({ id: user.id });
const oldPfpFilename = userRecord.pfpFilename;
if (oldPfpFilename) {
const storagePath = path.join(__dirname, "../storage/assets/pfp");
const oldPfpPath = path.join(
__dirname,
`../storage/assets/pfp/${normalizePath(userRecord.pfpFilename)}`
storagePath,
normalizePath(userRecord.pfpFilename)
);
if (!isWithin(path.resolve(storagePath), path.resolve(oldPfpPath)))
throw new Error("Invalid path name");
if (fs.existsSync(oldPfpPath)) fs.unlinkSync(oldPfpPath);
}
@ -655,13 +657,14 @@ function systemEndpoints(app) {
const userRecord = await User.get({ id: user.id });
const oldPfpFilename = userRecord.pfpFilename;
console.log("oldPfpFilename", oldPfpFilename);
if (oldPfpFilename) {
const storagePath = path.join(__dirname, "../storage/assets/pfp");
const oldPfpPath = path.join(
__dirname,
`../storage/assets/pfp/${normalizePath(oldPfpFilename)}`
storagePath,
normalizePath(oldPfpFilename)
);
if (!isWithin(path.resolve(storagePath), path.resolve(oldPfpPath)))
throw new Error("Invalid path name");
if (fs.existsSync(oldPfpPath)) fs.unlinkSync(oldPfpPath);
}

View File

@ -6,7 +6,7 @@ const {
userFromSession,
safeJsonParse,
} = require("../utils/http");
const { normalizePath } = require("../utils/files");
const { normalizePath, isWithin } = require("../utils/files");
const { Workspace } = require("../models/workspace");
const { Document } = require("../models/documents");
const { DocumentVectors } = require("../models/vectors");
@ -629,13 +629,13 @@ function workspaceEndpoints(app) {
const oldPfpFilename = workspaceRecord.pfpFilename;
if (oldPfpFilename) {
const storagePath = path.join(__dirname, "../storage/assets/pfp");
const oldPfpPath = path.join(
__dirname,
`../storage/assets/pfp/${normalizePath(
workspaceRecord.pfpFilename
)}`
storagePath,
normalizePath(workspaceRecord.pfpFilename)
);
if (!isWithin(path.resolve(storagePath), path.resolve(oldPfpPath)))
throw new Error("Invalid path name");
if (fs.existsSync(oldPfpPath)) fs.unlinkSync(oldPfpPath);
}
@ -670,11 +670,13 @@ function workspaceEndpoints(app) {
const oldPfpFilename = workspaceRecord.pfpFilename;
if (oldPfpFilename) {
const storagePath = path.join(__dirname, "../storage/assets/pfp");
const oldPfpPath = path.join(
__dirname,
`../storage/assets/pfp/${normalizePath(oldPfpFilename)}`
storagePath,
normalizePath(oldPfpFilename)
);
if (!isWithin(path.resolve(storagePath), path.resolve(oldPfpPath)))
throw new Error("Invalid path name");
if (fs.existsSync(oldPfpPath)) fs.unlinkSync(oldPfpPath);
}

View File

@ -3,7 +3,7 @@ const fs = require("fs");
const { getType } = require("mime");
const { v4 } = require("uuid");
const { SystemSettings } = require("../../models/systemSettings");
const { normalizePath } = require(".");
const { normalizePath, isWithin } = require(".");
const LOGO_FILENAME = "anything-llm.png";
function validFilename(newFilename = "") {
@ -23,6 +23,8 @@ async function determineLogoFilepath(defaultFilename = LOGO_FILENAME) {
if (currentLogoFilename && validFilename(currentLogoFilename)) {
customLogoPath = path.join(basePath, normalizePath(currentLogoFilename));
if (!isWithin(path.resolve(basePath), path.resolve(customLogoPath)))
return defaultFilepath;
return fs.existsSync(customLogoPath) ? customLogoPath : defaultFilepath;
}
@ -52,17 +54,17 @@ function fetchLogo(logoPath) {
async function renameLogoFile(originalFilename = null) {
const extname = path.extname(originalFilename) || ".png";
const newFilename = `${v4()}${extname}`;
const originalFilepath = process.env.STORAGE_DIR
? path.join(
process.env.STORAGE_DIR,
"assets",
normalizePath(originalFilename)
)
: path.join(
__dirname,
`../../storage/assets`,
normalizePath(originalFilename)
);
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));
@ -73,9 +75,13 @@ async function renameLogoFile(originalFilename = null) {
async function removeCustomLogo(logoFilename = LOGO_FILENAME) {
if (!logoFilename || !validFilename(logoFilename)) return false;
const logoPath = process.env.STORAGE_DIR
? path.join(process.env.STORAGE_DIR, `assets`, normalizePath(logoFilename))
: path.join(__dirname, `../../storage/assets`, normalizePath(logoFilename));
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)))
throw new Error("Invalid file path.");
if (fs.existsSync(logoPath)) fs.unlinkSync(logoPath);
return true;
}

View File

@ -2,7 +2,7 @@ const path = require("path");
const fs = require("fs");
const { getType } = require("mime");
const { User } = require("../../models/user");
const { normalizePath } = require(".");
const { normalizePath, isWithin } = require(".");
const { Workspace } = require("../../models/workspace");
function fetchPfp(pfpPath) {
@ -35,6 +35,8 @@ async function determinePfpFilepath(id) {
? path.join(process.env.STORAGE_DIR, "assets/pfp")
: path.join(__dirname, "../../storage/assets/pfp");
const pfpFilepath = path.join(basePath, normalizePath(pfpFilename));
if (!isWithin(path.resolve(basePath), path.resolve(pfpFilepath))) return null;
if (!fs.existsSync(pfpFilepath)) return null;
return pfpFilepath;
}
@ -48,6 +50,8 @@ async function determineWorkspacePfpFilepath(slug) {
? path.join(process.env.STORAGE_DIR, "assets/pfp")
: path.join(__dirname, "../../storage/assets/pfp");
const pfpFilepath = path.join(basePath, normalizePath(pfpFilename));
if (!isWithin(path.resolve(basePath), path.resolve(pfpFilepath))) return null;
if (!fs.existsSync(pfpFilepath)) return null;
return pfpFilepath;
}