forked from bai/curriculum-project-hub
41 lines
2.0 KiB
TypeScript
41 lines
2.0 KiB
TypeScript
/**
|
|
* 文件路径安全单测(Metis 安全红线:穿越/.git/分隔符/深度)。
|
|
*/
|
|
import { describe, expect, it } from "vitest";
|
|
import { validateFilePath, FILE_PATH_MAX_DEPTH, FILE_PATH_MAX_LENGTH } from "../../src/database/filelib/fileService.js";
|
|
import { FileLibError } from "../../src/database/filelib/model.js";
|
|
|
|
describe("validateFilePath · 路径安全", () => {
|
|
it("正常相对路径通过(含 CJK 与多级)", () => {
|
|
expect(validateFilePath("a.md")).toBe("a.md");
|
|
expect(validateFilePath("docs/讲义/第一课.md")).toBe("docs/讲义/第一课.md");
|
|
expect(validateFilePath("a/b/c/d.txt")).toBe("a/b/c/d.txt");
|
|
});
|
|
|
|
it("拒绝穿越:.. 段、绝对路径", () => {
|
|
expect(() => validateFilePath("../x")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("a/../../x")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("/etc/passwd")).toThrowError(FileLibError);
|
|
});
|
|
|
|
it("拒绝 .git 段与点段", () => {
|
|
expect(() => validateFilePath(".git")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("a/.git/config")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("./a.md")).toThrowError(FileLibError);
|
|
});
|
|
|
|
it("拒绝反斜杠、控制字符、空段(双斜杠/尾斜杠)", () => {
|
|
expect(() => validateFilePath("a\\b.md")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("a\nb.md")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("a//b.md")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("a/b/")).toThrowError(FileLibError);
|
|
});
|
|
|
|
it("拒绝空路径、超长、超深", () => {
|
|
expect(() => validateFilePath("")).toThrowError(FileLibError);
|
|
expect(() => validateFilePath("a".repeat(FILE_PATH_MAX_LENGTH + 1))).toThrowError(FileLibError);
|
|
expect(() => validateFilePath(Array(FILE_PATH_MAX_DEPTH + 1).fill("d").join("/"))).toThrowError(FileLibError);
|
|
expect(validateFilePath(Array(FILE_PATH_MAX_DEPTH).fill("d").join("/"))).toContain("d/");
|
|
});
|
|
});
|