refactor: consolidate agent/editor plugins under integrations/ (#5491)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Tests for path traversal prevention in skill-loader.
|
||||
*/
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { safePath, loadSkill } from "./skill-loader.ts";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// safePath — path containment
|
||||
// ---------------------------------------------------------------------------
|
||||
describe("safePath", () => {
|
||||
it("rejects parent directory traversal", () => {
|
||||
expect(safePath("../../etc/passwd")).toBeNull();
|
||||
});
|
||||
|
||||
it("rejects deep traversal", () => {
|
||||
expect(safePath("../../../etc/shadow")).toBeNull();
|
||||
});
|
||||
|
||||
it("rejects traversal in nested segment", () => {
|
||||
expect(safePath("valid", "../../etc")).toBeNull();
|
||||
});
|
||||
|
||||
it("rejects bare '..' as segment", () => {
|
||||
expect(safePath("..")).toBeNull();
|
||||
});
|
||||
|
||||
it("accepts valid skill paths", () => {
|
||||
expect(safePath("memory-triage", "SKILL.md")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("accepts valid domain overlay paths", () => {
|
||||
expect(safePath("memory-triage", "domains", "companion.md")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("returns null for empty segments that resolve to skills root with subpath escape", () => {
|
||||
// path.resolve("skills", "", "../../etc") still escapes
|
||||
expect(safePath("", "../../etc")).toBeNull();
|
||||
});
|
||||
|
||||
it("rejects traversal disguised with valid prefix", () => {
|
||||
expect(safePath("memory-triage/../../etc/passwd")).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// loadSkill — integration tests for traversal prevention
|
||||
// ---------------------------------------------------------------------------
|
||||
describe("loadSkill path traversal", () => {
|
||||
it("returns null for traversal skillName", () => {
|
||||
expect(loadSkill("../../etc/passwd")).toBeNull();
|
||||
});
|
||||
|
||||
it("returns null for deep traversal skillName", () => {
|
||||
expect(loadSkill("../../../..")).toBeNull();
|
||||
});
|
||||
|
||||
it("loads a valid skill", () => {
|
||||
const result = loadSkill("memory-triage");
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.prompt).toBeTruthy();
|
||||
});
|
||||
|
||||
it("blocks domain traversal while loading valid skill", () => {
|
||||
// Valid skill name, malicious domain — should load skill but skip the overlay
|
||||
const result = loadSkill("memory-triage", { domain: "../../etc/passwd" });
|
||||
// Should still succeed (skill itself is valid), domain overlay is just skipped
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.prompt).toBeTruthy();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user