fix: bound trans stdout and sanitize win ps json
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import {
|
||||
createSshStdoutForwarder,
|
||||
formatSshStdoutTruncationHint,
|
||||
parseSshInvocation,
|
||||
sshStdoutStreamMaxBytes,
|
||||
sshStdoutTruncationHint,
|
||||
windowsPowerShellScriptPrelude,
|
||||
} from "./ssh";
|
||||
|
||||
describe("ssh windows PowerShell safety prelude", () => {
|
||||
test("shadows ConvertTo-Json and strips filesystem ETS metadata", () => {
|
||||
const prelude = windowsPowerShellScriptPrelude("C:\\test");
|
||||
|
||||
expect(prelude).toContain("function ConvertTo-UniDeskPlainJsonValue");
|
||||
expect(prelude).toContain("function ConvertTo-Json");
|
||||
expect(prelude).toContain("'PSPath','PSParentPath','PSChildName','PSDrive','PSProvider','ReadCount'");
|
||||
expect(prelude).toContain("Microsoft.PowerShell.Utility\\ConvertTo-Json");
|
||||
expect(prelude).toContain("Set-Location -LiteralPath 'C:\\test'");
|
||||
});
|
||||
});
|
||||
|
||||
describe("ssh stdout bounded streaming", () => {
|
||||
test("uses bounded defaults and clamps env override", () => {
|
||||
expect(sshStdoutStreamMaxBytes({} as NodeJS.ProcessEnv)).toBe(256 * 1024);
|
||||
expect(sshStdoutStreamMaxBytes({ UNIDESK_SSH_STDOUT_STREAM_MAX_BYTES: "8192" } as NodeJS.ProcessEnv)).toBe(8192);
|
||||
expect(sshStdoutStreamMaxBytes({ UNIDESK_SSH_STDOUT_STREAM_MAX_BYTES: "1" } as NodeJS.ProcessEnv)).toBe(4096);
|
||||
expect(sshStdoutStreamMaxBytes({ UNIDESK_SSH_STDOUT_STREAM_MAX_BYTES: String(64 * 1024 * 1024) } as NodeJS.ProcessEnv)).toBe(16 * 1024 * 1024);
|
||||
});
|
||||
|
||||
test("formats truncation hint without echoing remote command", () => {
|
||||
const invocation = parseSshInvocation("D601:win", ["ps"]);
|
||||
expect(invocation.parsed.remoteCommand).not.toBeNull();
|
||||
const hint = sshStdoutTruncationHint({
|
||||
invocation,
|
||||
transport: "backend-core-broker",
|
||||
thresholdBytes: 4096,
|
||||
observedBytesAtTruncation: 5000,
|
||||
dumpPath: "/tmp/unidesk-cli-output/sample.stdout.bin",
|
||||
});
|
||||
const formatted = formatSshStdoutTruncationHint(hint);
|
||||
|
||||
expect(formatted.startsWith("UNIDESK_SSH_STDOUT_TRUNCATED ")).toBe(true);
|
||||
const payload = JSON.parse(formatted.slice("UNIDESK_SSH_STDOUT_TRUNCATED ".length)) as Record<string, unknown>;
|
||||
expect(payload.code).toBe("ssh-stdout-truncated");
|
||||
expect(payload.providerId).toBe("D601");
|
||||
expect(payload.route).toBe("D601:win");
|
||||
expect(payload.thresholdBytes).toBe(4096);
|
||||
expect(formatted).not.toContain("Get-Content");
|
||||
});
|
||||
|
||||
test("forwarder bounds stdout and emits one truncation hint", () => {
|
||||
const invocation = parseSshInvocation("D601:win", ["ps"]);
|
||||
const forwarded: Buffer[] = [];
|
||||
const stdout = {
|
||||
write(chunk: string | Buffer): boolean {
|
||||
forwarded.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
||||
return true;
|
||||
},
|
||||
} as NodeJS.WritableStream;
|
||||
const forwarder = createSshStdoutForwarder({
|
||||
invocation,
|
||||
transport: "frontend-websocket",
|
||||
maxBytes: 5,
|
||||
stdout,
|
||||
});
|
||||
|
||||
expect(forwarder.write(Buffer.from("abc"))).toBeNull();
|
||||
const hint = forwarder.write(Buffer.from("defgh"));
|
||||
expect(hint).not.toBeNull();
|
||||
expect(forwarder.write(Buffer.from("ijkl"))).toBeNull();
|
||||
expect(Buffer.concat(forwarded).toString("utf8")).toBe("abcde");
|
||||
expect(hint).toContain("UNIDESK_SSH_STDOUT_TRUNCATED");
|
||||
expect(hint).toContain("\"transport\":\"frontend-websocket\"");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user