fix path validation bug

This commit is contained in:
Nystik
2026-05-23 17:08:24 +02:00
parent 4fff803cbd
commit e6975d631c
3 changed files with 22 additions and 9 deletions

View File

@@ -263,8 +263,12 @@ router.post("/rename", async (req, res) => {
return;
}
const oldResolved = resolveVaultPath(vaultRoot, req.body?.oldPath);
const newResolved = resolveVaultPath(vaultRoot, req.body?.newPath);
if (!req.body?.oldPath || !req.body?.newPath) {
return res.status(400).json({ error: "Missing oldPath or newPath" });
}
const oldResolved = resolveVaultPath(vaultRoot, req.body.oldPath);
const newResolved = resolveVaultPath(vaultRoot, req.body.newPath);
if (!oldResolved || !newResolved) {
return res.status(403).json({ error: "Invalid path" });
@@ -288,8 +292,12 @@ router.post("/copyFile", async (req, res) => {
return;
}
const srcResolved = resolveVaultPath(vaultRoot, req.body?.src);
const destResolved = resolveVaultPath(vaultRoot, req.body?.dest);
if (!req.body?.src || !req.body?.dest) {
return res.status(400).json({ error: "Missing src or dest" });
}
const srcResolved = resolveVaultPath(vaultRoot, req.body.src);
const destResolved = resolveVaultPath(vaultRoot, req.body.dest);
if (!srcResolved || !destResolved) {
return res.status(403).json({ error: "Invalid path" });

View File

@@ -77,12 +77,12 @@ describe("resolveVaultPath", () => {
expect(resolveVaultPath(root, "")).toBe(path.resolve(root));
});
it("treats null input as vault root", () => {
expect(resolveVaultPath(root, null)).toBe(path.resolve(root));
it("returns null for null input", () => {
expect(resolveVaultPath(root, null)).toBe(null);
});
it("treats undefined input as vault root", () => {
expect(resolveVaultPath(root, undefined)).toBe(path.resolve(root));
it("returns null for undefined input", () => {
expect(resolveVaultPath(root, undefined)).toBe(null);
});
it("strips leading slashes", () => {

View File

@@ -46,8 +46,13 @@ function encodeContentDispositionFilename(filename) {
// Resolve a client-provided path to an absolute path within a vault.
// Strips leading slashes so paths from the client are always treated as relative to the vault root.
// Rejects nullish input so missing-field bugs in callers don't silently target the vault root.
function resolveVaultPath(vaultRoot, relativePath) {
const cleaned = (relativePath || "").replace(/^\/+/, "");
if (relativePath === null || relativePath === undefined) {
return null;
}
const cleaned = relativePath.replace(/^\/+/, "");
const resolved = path.resolve(vaultRoot, cleaned);
const resolvedRoot = path.resolve(vaultRoot);