// 路径权限单元测试:白名单 + 黑名单(黑名单优先) import { resolve, normalize } from "path"; function isWithin(base: string, target: string): boolean { const b = normalize(base).replace(/\\/g, "/").replace(/\/+$/, ""); const t = normalize(target).replace(/\\/g, "/").replace(/\/+$/, ""); return t === b || t.startsWith(b + "/"); } function makeAllowed(whitelist: string[], blacklist: string[], workspace: string) { return (p: string): boolean => { const abs = resolve(workspace, normalize(p)); for (const b of blacklist) if (isWithin(b, abs)) return false; const allowed = [...whitelist, workspace]; for (const w of allowed) if (isWithin(w, abs)) return true; return false; }; } const WS = "D:\\workbench\\miniai"; let pass = 0, fail = 0; function check(name: string, got: boolean, want: boolean) { const ok = got === want; console.log(`${ok ? "? : "?} ${name}: got=${got} want=${want}`); ok ? pass++ : fail++; } // 默认白名?= [d:\],无黑名?const a1 = makeAllowed(["d:\\"], [], WS); check("白名?d:\\ 根目录允?, a1("d:\\"), true); check("白名?d:\\ 子目录允?, a1("d:\\foo\\bar"), true); check("非白名单 c:\\ 拒绝", a1("c:\\windows"), false); check("工作区相对路径允?, a1("data.xlsx"), true); check("相对路径越权拒绝", a1("../../etc/passwd"), false); // 黑名单优?const a2 = makeAllowed(["d:\\"], ["c:\\"], WS); check("黑名?c:\\ 拒绝", a2("c:\\windows"), false); check("黑名单不影响白名?d:\\", a2("d:\\foo"), true); // 黑名单命中其下的子目录,即使父目录在白名?const a3 = makeAllowed(["d:\\"], ["d:\\secret"], WS); check("黑名单子目录拒绝(优先于白名单)", a3("d:\\secret\\x"), false); check("白名单其余部分仍允许", a3("d:\\pub"), true); console.log(`\n结果: ${pass} 通过, ${fail} 失败`); if (fail > 0) process.exit(1);