forked from farhoodlabs/paperclip
fix(plugin): harden kubernetes exec upload parsing
This commit is contained in:
@@ -59,6 +59,8 @@ export async function execInPod(
|
||||
stderrStream.on("data", (chunk: Buffer) => {
|
||||
stderrData += chunk.toString("utf-8");
|
||||
});
|
||||
stdoutStream.on("error", () => {});
|
||||
stderrStream.on("error", () => {});
|
||||
|
||||
return await new Promise<ExecInPodResult>(
|
||||
(resolve, reject) => {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { posix as pathPosix } from "node:path";
|
||||
const INIT_RE =
|
||||
/^mkdir -p '([^']+)' && rm -f '([^']+)\.paperclip-upload\.b64' && : > '\2\.paperclip-upload\.b64'$/;
|
||||
const CHUNK_RE =
|
||||
/^printf '%s' '([A-Za-z0-9+/=]+)' >> '([^']+)\.paperclip-upload\.b64'$/;
|
||||
/^printf '%s' '([A-Za-z0-9+/]+={0,2})' >> '([^']+)\.paperclip-upload\.b64'$/;
|
||||
const FINALIZE_RE =
|
||||
/^base64 -d < '([^']+)\.paperclip-upload\.b64' > '\1' && rm -f '\1\.paperclip-upload\.b64'$/;
|
||||
|
||||
|
||||
@@ -38,6 +38,17 @@ describe("execInPod", () => {
|
||||
expect(result).toEqual({ exitCode: 0, timedOut: false, stdout: "ok\n", stderr: "" });
|
||||
});
|
||||
|
||||
it("handles output stream errors after status completion", async () => {
|
||||
execMock.mockImplementation((_namespace, _pod, _container, _command, stdout, _stderr, _stdin, _tty, statusCallback) => {
|
||||
statusCallback({ status: "Success" });
|
||||
stdout.emit("error", new Error("write after end"));
|
||||
return Promise.resolve(new EventEmitter());
|
||||
});
|
||||
|
||||
const result = await execInPod({} as never, "ns", "pod-1", "agent", ["echo", "ok"]);
|
||||
expect(result).toEqual({ exitCode: 0, timedOut: false, stdout: "", stderr: "" });
|
||||
});
|
||||
|
||||
it("returns an execution failure if the websocket closes before a status frame", async () => {
|
||||
const ws = new EventEmitter();
|
||||
execMock.mockResolvedValue(ws);
|
||||
|
||||
@@ -46,6 +46,22 @@ describe("FastUploadInterceptor", () => {
|
||||
).toMatchObject({ action: "passthrough", reason: "finalize without buffered state" });
|
||||
});
|
||||
|
||||
it("does not intercept chunks with padding before the end", () => {
|
||||
const interceptor = new FastUploadInterceptor();
|
||||
const target = "/workspace/file.bin";
|
||||
|
||||
expect(
|
||||
interceptor.decide(
|
||||
`mkdir -p '/workspace' && rm -f '${target}.paperclip-upload.b64' && : > '${target}.paperclip-upload.b64'`,
|
||||
),
|
||||
).toMatchObject({ action: "ack" });
|
||||
|
||||
expect(
|
||||
interceptor.decide(`printf '%s' 'aGVs=bG8=' >> '${target}.paperclip-upload.b64'`),
|
||||
).toMatchObject({ action: "passthrough", reason: "no upload pattern" });
|
||||
expect(interceptor.pendingCount).toBe(1);
|
||||
});
|
||||
|
||||
it("falls through when the init command does not match the target parent directory", () => {
|
||||
const interceptor = new FastUploadInterceptor();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user