fix: avoid base64 eval wrappers in bash snapshots

This commit is contained in:
fengjun
2026-04-24 18:44:17 +08:00
parent c61a5b9a56
commit 0d4936b98f
2 changed files with 45 additions and 3 deletions
@@ -59,10 +59,9 @@ done
echo "# Functions" >> "$SNAPSHOT_FILE"
# Force autoload all functions first
declare -f > /dev/null 2>&1
# Get user function names - filter system/private ones, use base64 for special chars
# Get user function names - filter system/private ones
declare -F 2>/dev/null | cut -d' ' -f3 | grep -vE '^(_|__)' | grep -vE '${commonToolsRegex}' | while read func; do
encoded_func=$(declare -f "$func" | base64)
echo "eval \\"\\$(echo '$encoded_func' | base64 -d)\\" > /dev/null 2>&1" >> "$SNAPSHOT_FILE"
declare -f "$func" >> "$SNAPSHOT_FILE" 2>/dev/null
done
`;
@@ -309,6 +309,49 @@ describe("executeBash", () => {
expect(result.output.trim()).toBe("from_snapshot");
});
it("sources large bash functions without base64 eval wrappers", async () => {
if (process.platform === "win32") {
return;
}
const realBashPath = Bun.env.SHELL?.includes("bash") ? Bun.env.SHELL : "/bin/bash";
if (!fs.existsSync(realBashPath)) {
return;
}
const bashPath = path.join(tempDir, "test-bash");
fs.symlinkSync(realBashPath, bashPath);
const largeBody = Array.from({ length: 200 }, (_, index) => ` echo "snapshot ${index}"`).join("\n");
fs.writeFileSync(path.join(tempDir, ".bashrc"), `pi_snapshot_large_function ()\n{\n${largeBody}\n}\n`);
vi.spyOn(os, "homedir").mockReturnValue(tempDir);
vi.spyOn(Settings.prototype, "getShellConfig").mockReturnValue({
shell: bashPath,
args: ["-l", "-c"],
env: {
PATH: Bun.env.PATH ?? "",
HOME: tempDir,
},
prefix: undefined,
});
const snapshotPath = await shellSnapshot.getOrCreateSnapshot(bashPath, {
PATH: Bun.env.PATH ?? "",
HOME: tempDir,
});
expect(snapshotPath).not.toBeNull();
const snapshot = fs.readFileSync(snapshotPath!, "utf8");
expect(snapshot).toContain("pi_snapshot_large_function");
expect(snapshot).not.toContain("base64 -d");
const result = await executeBash("printf 'snapshot_ok\\n'", {
cwd: tempDir,
timeout: 5000,
sessionKey: "large-function-snapshot",
});
expect(result.cancelled).toBe(false);
expect(result.output.trim()).toBe("snapshot_ok");
});
it("does not allow exec to replace the host", async () => {
const result = await executeBash("exec echo hi", { cwd: tempDir, timeout: 5000 });
expect(result.cancelled).toBe(false);