fix: validate companyId/instanceId against path traversal (N1)

Co-Authored-By: Claude Sonnet <noreply@anthropic.com>
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-04-23 23:53:18 +00:00
parent e86b14a677
commit f64694f894
2 changed files with 58 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
import { describe, it, expect, vi } from "vitest";
import os from "node:os";
import path from "node:path";
import { prepareClaudePromptBundle } from "./prompt-cache.js";
const onLog = vi.fn();
describe("prepareClaudePromptBundle path traversal validation", () => {
const validArgs = {
skills: [],
instructionsContents: null,
onLog,
};
it("rejects companyId containing ..", async () => {
await expect(prepareClaudePromptBundle({ ...validArgs, companyId: ".." })).rejects.toThrow(/companyId/);
});
it("rejects companyId containing ../x", async () => {
await expect(prepareClaudePromptBundle({ ...validArgs, companyId: "../x" })).rejects.toThrow(/companyId/);
});
it("rejects companyId containing /", async () => {
await expect(prepareClaudePromptBundle({ ...validArgs, companyId: "a/b" })).rejects.toThrow(/companyId/);
});
it("rejects companyId containing backslash", async () => {
await expect(prepareClaudePromptBundle({ ...validArgs, companyId: "a\\b" })).rejects.toThrow(/companyId/);
});
it("rejects companyId containing null byte", async () => {
await expect(prepareClaudePromptBundle({ ...validArgs, companyId: "a\0b" })).rejects.toThrow(/companyId/);
});
it("rejects empty companyId", async () => {
await expect(prepareClaudePromptBundle({ ...validArgs, companyId: "" })).rejects.toThrow(/companyId/);
});
it("rejects whitespace-only companyId", async () => {
await expect(prepareClaudePromptBundle({ ...validArgs, companyId: " " })).rejects.toThrow(/companyId/);
});
it("accepts a valid companyId", async () => {
vi.stubEnv("PAPERCLIP_HOME", path.join(os.tmpdir(), `prompt-cache-test-${process.pid}`));
const result = await prepareClaudePromptBundle({ ...validArgs, companyId: "acme-co" });
expect(result.rootDir).toContain("acme-co");
vi.unstubAllEnvs();
});
});