import * as fs from "node:fs"; import * as path from "node:path"; import * as os from "node:os"; import { SecurityVerification } from "../verification/security.js"; describe("SecurityVerification", () => { let tempDir: string; beforeEach(() => { tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-security-test-")); }); afterEach(() => { fs.rmSync(tempDir, { recursive: true, force: true }); }); it("passes when no security threats detected", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "app.ts"), "export function main() { return 1; }"); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n"); const verifier = new SecurityVerification(); const result = await verifier.verify(tempDir, 1); expect(result.layer).toBe(3); expect(result.name).toBe("Security"); const highThreatsCheck = result.checks.find((c) => c.name.includes("High severity")); expect(highThreatsCheck?.status).toBe("pass"); }); it("detects hardcoded passwords as high severity", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "config.ts"), 'const password = "supersecret123";'); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n"); const verifier = new SecurityVerification(); const result = await verifier.verify(tempDir, 1); const highCheck = result.checks.find((c) => c.name.includes("High severity")); expect(highCheck?.status).toBe("fail"); }); it("detects hardcoded API keys", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "api.ts"), 'const api_key = "abc123def456";'); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n"); const verifier = new SecurityVerification(); const result = await verifier.verify(tempDir, 1); const highCheck = result.checks.find((c) => c.name.includes("High severity")); expect(highCheck?.status).toBe("fail"); }); it("detects eval() usage", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "eval.ts"), 'function run(code: string) { eval(code); }'); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n.env\n"); const verifier = new SecurityVerification(); const result = await verifier.verify(tempDir, 1); const highCheck = result.checks.find((c) => c.name.includes("High severity")); expect(highCheck?.status).toBe("fail"); }); it("warns about missing .gitignore patterns", async () => { const srcDir = path.join(tempDir, "src"); fs.mkdirSync(srcDir, { recursive: true }); fs.writeFileSync(path.join(srcDir, "app.ts"), "export function main() { return 1; }"); fs.writeFileSync(path.join(tempDir, ".gitignore"), "node_modules\n"); const verifier = new SecurityVerification(); const result = await verifier.verify(tempDir, 1); const gitignoreCheck = result.checks.find((c) => c.name.includes(".gitignore")); expect(gitignoreCheck?.status).toBe("warning"); }); it("skips checks when no src/ directory", async () => { const verifier = new SecurityVerification(); const result = await verifier.verify(tempDir, 1); const lowCheck = result.checks.find((c) => c.name.includes("Low severity")); expect(lowCheck?.status).toBe("pass"); }); });