Files
hypothesis-machine/tests/confine.test.ts
T
Emil b53687c2b9 fix: keep pause/resume in sync between loop and tree; close read_artifact symlink escape
- research_control pause/resume now validate the loop state before touching
  the tree, so pausing a stopped loop can no longer leave the tree 'paused'
  while the loop is not (spawn would fail until a restart).
- read_artifact confinement resolves symlinks (realpath) before checking the
  project boundary, preventing symlink-based file leaks.
- Adds confinement tests (42 tests passing, tsc clean).
2026-07-31 23:09:20 +03:00

24 lines
1.1 KiB
TypeScript

import { mkdtempSync, symlinkSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
import { confined } from "../src/tools/index.js";
describe("read_artifact confinement", () => {
it("rejects paths that escape the project directory lexically", () => {
const root = mkdtempSync(resolve(tmpdir(), "hm-confine-"));
expect(() => confined(root, "../../etc/passwd")).toThrow(/escapes/);
});
it("rejects symlinks that point outside the project directory", () => {
const root = mkdtempSync(resolve(tmpdir(), "hm-confine-"));
const outside = mkdtempSync(resolve(tmpdir(), "hm-outside-"));
const target = resolve(outside, "secret.txt"); writeFileSync(target, "secret");
const link = resolve(root, "leak.md"); symlinkSync(target, link);
expect(() => confined(root, "leak.md")).toThrow(/escapes/);
});
it("allows paths inside the project directory", () => {
const root = mkdtempSync(resolve(tmpdir(), "hm-confine-"));
expect(confined(root, "memory/findings/x.md")).toBe(resolve(root, "memory/findings/x.md"));
});
});