mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-10 06:42:34 +00:00
Fix what three platforms found: two shipped bugs, four unportable tests
The platform workflow's first run produced seventeen failures on Windows and macOS, where the JavaScript suite had never executed. Two were real defects in shipped code. A CONTAINMENT CHECK THAT REFUSED EVERYTHING ON WINDOWS `resolveWithinProfile` compared `target.startsWith(root + "/")` with a hardcoded forward slash. On Windows `resolve()` returns `C:\profile\file.txt` and the comparison asked for `C:\profile/`, so it matched nothing: document export and import refused every path, including legitimate ones. It failed CLOSED, so nothing leaked — the feature simply did not work. Now uses `relative()`, which needs no separator of our choosing. A COMMAND PARSER THAT ATE WINDOWS PATHS `parseCommandSpec` treated backslash as a POSIX escape unconditionally, so `--exec "C:\Program Files\tool.exe"` was spawned as the command `C:Program` with an argument `Filestool.exe`. Every Windows path handed to --exec or --stdin-to was mangled before the spawn. This is the SECOND instance of this exact bug today — the Python TUI palette had it too — which is what a whole class looks like rather than a one-off. `windows` is an explicit parameter, not a `process.platform` read, so both branches are tested from either platform. That parameter is the actual fix for the class: the reason these survived is that the Windows branch could only ever run on Windows. THE REST WERE TESTS, NOT CODE - `/bin/true` does not exist on macOS (it is /usr/bin/true), so a spawn failed with ENOENT and the refusal looked like the daemon's crash-safety fix having regressed. Now uses process.execPath, which exists everywhere by definition. - The oversized-request test treated its own EPIPE as fatal. The daemon caps the line, answers and hangs up; on macOS that hangup lands while the client is still pushing the remaining megabyte. Correct server behaviour was failing the test on one platform and passing on the other. - Three sink tests wrote `#!/bin/sh` files. Shebangs and /bin/sh do not exist on Windows. Now Node scripts run by the interpreter already running the tests. - Eight `0600` assertions and two clipboard tests are guarded by documented constants in test/helpers/platform.ts. Windows has no POSIX mode bits and the runner has no clipboard. The skips state a gap rather than closing it, and TODO.md now records that the Windows permissions question grew from two Python tests to ten across both languages — including the vault index and the semantic index, which hold secrets. With TypeScript becoming the only implementation that is a shipping question, not a test-suite one. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01Vtx94nXDmNgXEeThUZP4QN
This commit is contained in:
1 parent
4edf50e5de
commit
e2e9aa851e
13 files changed
+213
-32
No files matched your search
@@ -217,12 +217,19 @@ describe("sink delivery keeps secrets out of CLI output", () => {
|
||||
it("use --exec injects SEEDPASS_SECRET into the child env only", async () => {
|
||||
const dir = await mkdtemp(join(tmpdir(), "seedpass-sink-"));
|
||||
const capture = join(dir, "captured.txt");
|
||||
const script = join(dir, "cap.sh");
|
||||
await writeFile(script, `#!/bin/sh\nprintf '%s' "$SEEDPASS_SECRET" > "${capture}"\n`, {
|
||||
mode: 0o755,
|
||||
});
|
||||
// A Node script run by the interpreter already running these tests,
|
||||
// rather than a `#!/bin/sh` file. Shebangs and /bin/sh do not exist on
|
||||
// Windows, so this whole describe block failed there the first time the
|
||||
// suite ran on it. `process.execPath` exists on every platform by
|
||||
// definition, and quoting the spec lets a path with spaces survive.
|
||||
const script = join(dir, "cap.cjs");
|
||||
await writeFile(
|
||||
script,
|
||||
`require("fs").writeFileSync(${JSON.stringify(capture)}, process.env.SEEDPASS_SECRET ?? "");`,
|
||||
);
|
||||
|
||||
const r = await run("--vault", vaultPath, "use", "api-token", "--exec", script);
|
||||
const spec = `"${process.execPath}" "${script}"`;
|
||||
const r = await run("--vault", vaultPath, "use", "api-token", "--exec", spec);
|
||||
const delivered = JSON.parse(r.stdout);
|
||||
expect(delivered.sink).toBe("exec");
|
||||
expect(delivered.exitCode).toBe(0);
|
||||
@@ -237,10 +244,17 @@ describe("sink delivery keeps secrets out of CLI output", () => {
|
||||
it("use --stdin-to pipes the secret to the command's stdin", async () => {
|
||||
const dir = await mkdtemp(join(tmpdir(), "seedpass-sink-"));
|
||||
const capture = join(dir, "captured.txt");
|
||||
const script = join(dir, "cap.sh");
|
||||
await writeFile(script, `#!/bin/sh\ncat > "${capture}"\n`, { mode: 0o755 });
|
||||
const script = join(dir, "cap.cjs");
|
||||
await writeFile(
|
||||
script,
|
||||
`let b = "";
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", (d) => { b += d; });
|
||||
process.stdin.on("end", () => require("fs").writeFileSync(${JSON.stringify(capture)}, b));`,
|
||||
);
|
||||
|
||||
const r = await run("--vault", vaultPath, "use", "api-token", "--stdin-to", script);
|
||||
const spec = `"${process.execPath}" "${script}"`;
|
||||
const r = await run("--vault", vaultPath, "use", "api-token", "--stdin-to", spec);
|
||||
expect(JSON.parse(r.stdout).sink).toBe("stdin");
|
||||
expect(await readFile(capture, "utf8")).toBe("abc123");
|
||||
expect(r.stdout).not.toContain("abc123");
|
||||
@@ -252,12 +266,18 @@ describe("sink delivery keeps secrets out of CLI output", () => {
|
||||
// way to include flags.
|
||||
const dir = await mkdtemp(join(tmpdir(), "seedpass-spec-"));
|
||||
const capture = join(dir, "captured.txt");
|
||||
const script = join(dir, "cap.sh");
|
||||
await writeFile(script, `#!/bin/sh\nprintf '%s %s' "$1" "$(cat)" > "${capture}"\n`, {
|
||||
mode: 0o755,
|
||||
});
|
||||
const script = join(dir, "cap.cjs");
|
||||
await writeFile(
|
||||
script,
|
||||
`let b = "";
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", (d) => { b += d; });
|
||||
process.stdin.on("end", () =>
|
||||
require("fs").writeFileSync(${JSON.stringify(capture)}, process.argv[2] + " " + b));`,
|
||||
);
|
||||
const r = await run(
|
||||
"--vault", vaultPath, "use", "api-token", "--stdin-to", `${script} -flagged`,
|
||||
"--vault", vaultPath, "use", "api-token",
|
||||
"--stdin-to", `"${process.execPath}" "${script}" -flagged`,
|
||||
);
|
||||
expect(JSON.parse(r.stdout).sink).toBe("stdin");
|
||||
expect(await readFile(capture, "utf8")).toBe("-flagged abc123");
|
||||
|
||||
Reference in new issue
Block a user