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");
});
});