mirror of
https://git.quad4.io/RNS-Things/MeshChatX.git
synced 2026-04-27 19:25:58 +00:00
84 lines
2.8 KiB
JavaScript
84 lines
2.8 KiB
JavaScript
"use strict";
|
|
|
|
import fs from "fs";
|
|
import os from "os";
|
|
import path from "path";
|
|
import { describe, expect, it } from "vitest";
|
|
import { isAllowedShellPath } from "../../electron/shellPathGuard.js";
|
|
|
|
function fakeApp() {
|
|
const home = os.homedir();
|
|
return {
|
|
getPath(name) {
|
|
if (name === "userData") {
|
|
return path.join(home, ".meshchatx-test-userdata");
|
|
}
|
|
if (name === "temp") {
|
|
return os.tmpdir();
|
|
}
|
|
if (name === "downloads") {
|
|
return path.join(home, "Downloads");
|
|
}
|
|
if (name === "documents") {
|
|
return path.join(home, "Documents");
|
|
}
|
|
throw new Error(`unexpected getPath ${name}`);
|
|
},
|
|
};
|
|
}
|
|
|
|
describe("shellPathGuard", () => {
|
|
const home = os.homedir();
|
|
const storage = path.join(home, ".reticulum-meshchat");
|
|
const reticulum = path.join(home, ".reticulum");
|
|
const ctx = {
|
|
app: fakeApp(),
|
|
getDefaultStorageDir: () => storage,
|
|
getDefaultReticulumConfigDir: () => reticulum,
|
|
getUserProvidedArguments: () => [],
|
|
};
|
|
|
|
it("allows paths under default storage", () => {
|
|
const p = path.join(storage, "rncp_received", "file.bin");
|
|
expect(isAllowedShellPath(p, ctx)).toBe(true);
|
|
});
|
|
|
|
it("denies paths outside allowed roots", () => {
|
|
const p = process.platform === "win32" ? "C:\\Windows\\System32\\drivers\\etc\\hosts" : "/etc/passwd";
|
|
expect(isAllowedShellPath(p, ctx)).toBe(false);
|
|
});
|
|
|
|
it("allows temp directory files", () => {
|
|
const p = path.join(os.tmpdir(), `meshchatx-shell-guard-${process.pid}.txt`);
|
|
fs.writeFileSync(p, "x");
|
|
try {
|
|
expect(isAllowedShellPath(p, ctx)).toBe(true);
|
|
} finally {
|
|
fs.unlinkSync(p);
|
|
}
|
|
});
|
|
|
|
it("fuzz: paths under default storage stay allowed", () => {
|
|
for (let i = 0; i < 200; i++) {
|
|
const seg = Array.from({ length: 10 }, () => String.fromCharCode(Math.floor(Math.random() * 94) + 33)).join(
|
|
""
|
|
);
|
|
const p = path.join(storage, "fuzz-shell", seg);
|
|
expect(() => isAllowedShellPath(p, ctx)).not.toThrow();
|
|
expect(isAllowedShellPath(p, ctx)).toBe(true);
|
|
}
|
|
});
|
|
|
|
it("fuzz: random absolute-looking paths return boolean without throw", () => {
|
|
for (let i = 0; i < 200; i++) {
|
|
let s = process.platform === "win32" ? "C:\\" : "/";
|
|
const n = Math.floor(Math.random() * 24) + 4;
|
|
for (let j = 0; j < n; j++) {
|
|
s += String.fromCharCode(Math.floor(Math.random() * 96) + 32);
|
|
}
|
|
expect(() => isAllowedShellPath(s, ctx)).not.toThrow();
|
|
expect(typeof isAllowedShellPath(s, ctx)).toBe("boolean");
|
|
}
|
|
});
|
|
});
|