all repos — sz-chrome-remote-extension @ master

pi-chrome, patched to drive a signed-in browser on another host through a broker, with an MCP server

test-suite/unit/upload-guard.test.mjs (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { test } from "node:test";
import { assertUploadsStaged } from "../../broker/upload-guard.mjs";

const base = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), "guard-")));
const stage = path.join(base, "stage");
fs.mkdirSync(stage);
fs.writeFileSync(path.join(stage, "ok.txt"), "x");
fs.writeFileSync(path.join(base, "secret.txt"), "s");
fs.symlinkSync(path.join(base, "secret.txt"), path.join(stage, "link.txt"));

const upload = (...paths) => () => assertUploadsStaged("page.upload", { paths }, stage);

test("a file in the staging directory is allowed", () => {
	assert.doesNotThrow(upload(path.join(stage, "ok.txt")));
});
test("a file elsewhere, a ../ escape, a symlink out, a relative path and a missing file are refused", () => {
	assert.throws(upload(path.join(base, "secret.txt")), /limited to files/);
	assert.throws(upload(path.join(stage, "..", "secret.txt")), /limited to files/);
	assert.throws(upload(path.join(stage, "link.txt")), /limited to files/);
	assert.throws(upload("ok.txt"), /limited to files/);
	assert.throws(upload(path.join(stage, "nope.txt")), /limited to files/);
});
test("one bad path among good ones refuses the lot", () => {
	assert.throws(upload(path.join(stage, "ok.txt"), "/etc/hosts"), /limited to files/);
});
test("a missing staging directory refuses everything", () => {
	assert.throws(() => assertUploadsStaged("page.upload", { paths: [path.join(stage, "ok.txt")] }, path.join(base, "none")), /limited to files/);
});
test("raw DOM.setFileInputFiles through cdp.call is held to the same rule", () => {
	const call = (files) => () => assertUploadsStaged("cdp.call", { method: "DOM.setFileInputFiles", params: { files } }, stage);
	assert.doesNotThrow(call([path.join(stage, "ok.txt")]));
	assert.throws(call(["/etc/hosts"]), /limited to files/);
});
test("other commands are untouched", () => {
	assert.doesNotThrow(() => assertUploadsStaged("page.click", { paths: ["/etc/hosts"] }, stage));
	assert.doesNotThrow(() => assertUploadsStaged("cdp.call", { method: "Runtime.evaluate", params: {} }, stage));
});