refactor: unify boundary hardening for file reads

This commit is contained in:
Peter Steinberger
2026-02-26 13:04:33 +01:00
parent cf4853e2b8
commit eac86c2081
11 changed files with 455 additions and 56 deletions

View File

@@ -102,4 +102,67 @@ describe("hooks workspace", () => {
const entries = loadHookEntriesFromDir({ dir: hooksRoot, source: "openclaw-workspace" });
expect(entries.some((e) => e.hook.name === "outside")).toBe(false);
});
it("ignores hooks with hardlinked HOOK.md aliases", () => {
if (process.platform === "win32") {
return;
}
const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-hooks-workspace-hardlink-"));
const hooksRoot = path.join(root, "hooks");
fs.mkdirSync(hooksRoot, { recursive: true });
const hookDir = path.join(hooksRoot, "hardlink-hook");
const outsideDir = path.join(root, "outside");
fs.mkdirSync(hookDir, { recursive: true });
fs.mkdirSync(outsideDir, { recursive: true });
fs.writeFileSync(path.join(hookDir, "handler.js"), "export default async () => {};\n");
const outsideHookMd = path.join(outsideDir, "HOOK.md");
const linkedHookMd = path.join(hookDir, "HOOK.md");
fs.writeFileSync(linkedHookMd, "---\nname: hardlink-hook\n---\n");
fs.rmSync(linkedHookMd);
fs.writeFileSync(outsideHookMd, "---\nname: outside\n---\n");
try {
fs.linkSync(outsideHookMd, linkedHookMd);
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "EXDEV") {
return;
}
throw err;
}
const entries = loadHookEntriesFromDir({ dir: hooksRoot, source: "openclaw-workspace" });
expect(entries.some((e) => e.hook.name === "hardlink-hook")).toBe(false);
expect(entries.some((e) => e.hook.name === "outside")).toBe(false);
});
it("ignores hooks with hardlinked handler aliases", () => {
if (process.platform === "win32") {
return;
}
const root = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-hooks-workspace-hardlink-"));
const hooksRoot = path.join(root, "hooks");
fs.mkdirSync(hooksRoot, { recursive: true });
const hookDir = path.join(hooksRoot, "hardlink-handler-hook");
const outsideDir = path.join(root, "outside");
fs.mkdirSync(hookDir, { recursive: true });
fs.mkdirSync(outsideDir, { recursive: true });
fs.writeFileSync(path.join(hookDir, "HOOK.md"), "---\nname: hardlink-handler-hook\n---\n");
const outsideHandler = path.join(outsideDir, "handler.js");
const linkedHandler = path.join(hookDir, "handler.js");
fs.writeFileSync(outsideHandler, "export default async () => {};\n");
try {
fs.linkSync(outsideHandler, linkedHandler);
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "EXDEV") {
return;
}
throw err;
}
const entries = loadHookEntriesFromDir({ dir: hooksRoot, source: "openclaw-workspace" });
expect(entries.some((e) => e.hook.name === "hardlink-handler-hook")).toBe(false);
});
});