




























@@ -187,17 +187,34 @@ describe("exec approvals store helpers", () => {
187187expect(fs.readFileSync(targetPath, "utf8")).toBe('{"sentinel":true}\n');
188188});
189189190-it("refuses to traverse a symlinked parent component in the approvals path", () => {
190+it("accepts a symlinked OPENCLAW_HOME as the trusted approvals root", () => {
191191const realHome = makeTempDir();
192192const linkedHome = `${realHome}-link`;
193-tempDirs.push(realHome);
194-fs.symlinkSync(realHome, linkedHome);
193+tempDirs.push(realHome, linkedHome);
194+fs.symlinkSync(realHome, linkedHome, "dir");
195+process.env.OPENCLAW_HOME = linkedHome;
196+197+saveExecApprovals({ version: 1, defaults: { security: "full" }, agents: {} });
198+199+expect(
200+fs.readFileSync(path.join(realHome, ".openclaw", "exec-approvals.json"), "utf8"),
201+).toContain('"security": "full"');
202+});
203+204+it("refuses to traverse symlinked approvals components below a symlinked home", () => {
205+const realHome = makeTempDir();
206+const linkedHome = `${realHome}-link`;
207+const linkedStateTarget = path.join(realHome, "state-target");
208+tempDirs.push(realHome, linkedHome);
209+fs.mkdirSync(linkedStateTarget, { recursive: true });
210+fs.symlinkSync(realHome, linkedHome, "dir");
211+fs.symlinkSync(linkedStateTarget, path.join(realHome, ".openclaw"), "dir");
195212process.env.OPENCLAW_HOME = linkedHome;
196213197214expect(() =>
198215saveExecApprovals({ version: 1, defaults: { security: "full" }, agents: {} }),
199216).toThrow(/Refusing to traverse symlink in exec approvals path/);
200-expect(fs.existsSync(path.join(realHome, ".openclaw"))).toBe(false);
217+expect(fs.existsSync(path.join(linkedStateTarget, "exec-approvals.json"))).toBe(false);
201218});
202219203220it("adds trimmed allowlist entries once and persists generated ids", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。