test(cli): the default Claude pin goes through the exec and character checks (#1572, row 78)
Two default-pin cases (no --claude): the only claude on PATH is mode 0644, and claude in a PATH dir with a space. render exits 1 with stdout empty for each. PATH holds only the test's dirs. Author Rocko, reviewer Filbert (27560), candidate manifest 3016dbf1. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -611,3 +611,41 @@ test("bus-service.sh refuses a directory pin and keeps a symlink default unresol
|
||||
assert.equal(pinned(r.stdout), join(linkBin, "claude"));
|
||||
assert.ok(!r.stdout.includes(real), "the target never reaches the unit");
|
||||
});
|
||||
|
||||
// Row 78 (#1572): the default from `command -v claude` takes the same checks
|
||||
// as --claude. PATH holds only the test's dirs, so a real claude elsewhere on
|
||||
// the host can't stand in for the one under test.
|
||||
test("bus-service.sh refuses a default claude without the execute bit, or in a PATH dir with a space", (t) => {
|
||||
const dir = tmp(t);
|
||||
const script = join(REPO, "scripts", "bus-service.sh");
|
||||
const tools = join(dir, "tools");
|
||||
mkdirSync(tools);
|
||||
symlinkSync(process.execPath, join(tools, "node"));
|
||||
for (const tool of ["dirname", "sed", "readlink"]) {
|
||||
const at = ["/usr/bin", "/bin"].map((d) => join(d, tool)).find((p) => existsSync(p));
|
||||
symlinkSync(at, join(tools, tool));
|
||||
}
|
||||
const bash = ["/usr/bin/bash", "/bin/bash"].find((p) => existsSync(p));
|
||||
const run = (bin) => spawnSync(bash, [script, "render"], { encoding: "utf8", env: { PATH: `${bin}:${tools}`, HOME: dir } });
|
||||
const stand = (bin, mode) => {
|
||||
mkdirSync(bin);
|
||||
writeFileSync(join(bin, "claude"), '#!/bin/sh\necho "9.9.9 (Claude Code)"\n');
|
||||
chmodSync(join(bin, "claude"), mode);
|
||||
return bin;
|
||||
};
|
||||
|
||||
// The only claude on PATH has no execute bit: `command -v` still returns
|
||||
// it, and the -x check refuses it.
|
||||
let r = run(stand(join(dir, "noexec-bin"), 0o644));
|
||||
assert.equal(r.status, 1);
|
||||
assert.match(r.stderr, /not an executable file/);
|
||||
assert.equal(r.stdout, "");
|
||||
|
||||
// claude in a PATH dir with a space: systemd would split the pin there.
|
||||
const spaced = stand(join(dir, "spaced bin"), 0o755);
|
||||
r = run(spaced);
|
||||
assert.equal(r.status, 1);
|
||||
assert.match(r.stderr, /cannot carry/);
|
||||
assert.ok(r.stderr.includes(join(spaced, "claude")), r.stderr);
|
||||
assert.equal(r.stdout, "");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user