45 lines
1.9 KiB
TypeScript
45 lines
1.9 KiB
TypeScript
// 路径æ<E2809E>ƒé™<C3A9>å<EFBFBD>•元测试:白å<C2BD><C3A5>å<EFBFBD>• + 黑å<E28098><C3A5>å<EFBFBD>•(黑å<E28098><C3A5>å<EFBFBD>•优先)
|
||
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 ? "âœ? : "â<EFBFBD>?} ${name}: got=${got} want=${want}`);
|
||
ok ? pass++ : fail++;
|
||
}
|
||
|
||
// 默认白å<C2BD><C3A5>å<EFBFBD>?= [d:\]ï¼Œæ— é»‘å<E28098><C3A5>å<EFBFBD>?const a1 = makeAllowed(["d:\\"], [], WS);
|
||
check("白å<C2BD><C3A5>å<EFBFBD>?d:\\ æ ¹ç›®å½•å…<C3A5>è®?, a1("d:\\"), true);
|
||
check("白å<EFBFBD><EFBFBD>å<EFBFBD>?d:\\ å<EFBFBD>目录å…<EFBFBD>è®?, a1("d:\\foo\\bar"), true);
|
||
check("é<>žç™½å<C2BD><C3A5>å<EFBFBD>• c:\\ æ‹’ç»<C3A7>", a1("c:\\windows"), false);
|
||
check("工作区相对路径å…<C3A5>è®?, a1("data.xlsx"), true);
|
||
check("相对路径越æ<EFBFBD>ƒæ‹’ç»<EFBFBD>", a1("../../etc/passwd"), false);
|
||
|
||
// 黑å<E28098><C3A5>å<EFBFBD>•优å…?const a2 = makeAllowed(["d:\\"], ["c:\\"], WS);
|
||
check("黑å<EFBFBD><EFBFBD>å<EFBFBD>?c:\\ æ‹’ç»<EFBFBD>", a2("c:\\windows"), false);
|
||
check("黑å<EFBFBD><EFBFBD>å<EFBFBD>•ä¸<EFBFBD>å½±å“<EFBFBD>白å<EFBFBD><EFBFBD>å<EFBFBD>?d:\\", a2("d:\\foo"), true);
|
||
|
||
// 黑å<E28098><C3A5>å<EFBFBD>•命ä¸å…¶ä¸‹çš„å<C3A5>目录,å<C592>³ä½¿çˆ¶ç›®å½•在白å<C2BD><C3A5>å<EFBFBD>?const a3 = makeAllowed(["d:\\"], ["d:\\secret"], WS);
|
||
check("黑å<EFBFBD><EFBFBD>å<EFBFBD>•å<EFBFBD>目录拒ç»<EFBFBD>(优先于白å<EFBFBD><EFBFBD>å<EFBFBD>•)", a3("d:\\secret\\x"), false);
|
||
check("白å<EFBFBD><EFBFBD>å<EFBFBD>•其余部分ä»<EFBFBD>å…<EFBFBD>许", a3("d:\\pub"), true);
|
||
|
||
console.log(`\n结果: ${pass} 通过, ${fail} 失败`);
|
||
if (fail > 0) process.exit(1);
|