g1t/apps/web/app/lib/security-alerts.test.ts

170 lines6,002 bytesCodeBlame

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Git storage hardened, pages in tens of milliseconds, honest security alerts, and costs reconciled daily1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import type { AlertActivity, SecretFinding, Vulnerability } from "@g1t/contracts";
5
6import {
7 alertActivity,
8 alertCapability,
9 compareVersions,
10 countByState,
11 groupByPackage,
12 highestFix,
13 latestUpdate,
14 parseAlertState,
15 splitSecrets,
16 tabOf,
17 worstSeverity,
18} from "./security-alerts.ts";
19
20const secret = (over: Partial<SecretFinding> = {}): SecretFinding => ({
21 id: "sec_1",
22 repoId: "r",
23 kind: "aws_access_key",
24 label: "an AWS access key",
25 path: "src/config.ts",
26 line: 4,
27 commit: "abcdef1234",
28 preview: "AKIA…WXYZ",
29 status: "open",
30 source: "history",
31 foundBy: null,
32 foundAt: "2026-10-01T10:00:00Z",
33 decidedBy: null,
34 reason: null,
35 decidedAt: null,
36 state: "open",
37 ...over,
38});
39
40const vuln = (over: Partial<Vulnerability> = {}): Vulnerability => ({
41 id: "vul_1",
42 repoId: "r",
43 ecosystem: "npm",
44 package: "lodash",
45 version: "4.17.20",
46 manifest: "package-lock.json",
47 advisory: "GHSA-1",
48 osvId: "GHSA-1",
49 summary: "Prototype pollution",
50 severity: "high",
51 fixedVersion: "4.17.21",
52 status: "open",
53 issue: null,
54 foundAt: "2026-10-01T10:00:00Z",
55 fixedAt: null,
56 state: "open",
57 ...over,
58});
59
60test("the state parameter falls back to open", () => {
61 assert.equal(parseAlertState(null), "open");
62 assert.equal(parseAlertState("dismissed"), "dismissed");
63 assert.equal(parseAlertState("fixed"), "fixed");
64 assert.equal(parseAlertState("nonsense"), "open");
65});
66
67test("ids say which tab and which role an alert takes", () => {
68 assert.equal(tabOf("sec_9"), "secrets");
69 assert.equal(tabOf("vul_9"), "dependencies");
70 assert.equal(alertCapability("sec_9"), "manage_integrations");
71 assert.equal(alertCapability("vul_9"), "push");
72});
73
74test("alerts are counted by state", () => {
75 assert.deepEqual(countByState([secret(), secret({ state: "dismissed" }), secret({ state: "fixed" }), secret()]), {
76 open: 2,
77 dismissed: 1,
78 fixed: 1,
79 });
80});
81
82test("likely test values are listed apart from real secrets", () => {
83 const real = secret({ id: "sec_real" });
84 const fake = secret({ id: "sec_fake", testValue: "AWS's documented example key" });
85 const { real: shown, tests } = splitSecrets([fake, real]);
86 assert.deepEqual(shown.map((s) => s.id), ["sec_real"]);
87 assert.deepEqual(tests.map((s) => s.id), ["sec_fake"]);
88});
89
90test("packages group their alerts and take the worst severity", () => {
91 const groups = groupByPackage([
92 vuln({ id: "vul_1", severity: "medium" }),
93 vuln({ id: "vul_2", package: "express" }),
94 vuln({ id: "vul_3", severity: "critical", fixedVersion: "4.17.3" }),
95 ]);
96 assert.deepEqual(groups.map((g) => g.name), ["lodash", "express"]);
97 assert.equal(worstSeverity(groups[0].vulns), "critical");
98 assert.equal(highestFix(groups[0].vulns), "4.17.21");
99});
100
101test("versions compare number by number", () => {
102 assert.ok(compareVersions("4.17.10", "4.17.9") > 0);
103 assert.ok(compareVersions("1.2.0", "1.10.0") < 0);
104 assert.equal(highestFix([vuln({ fixedVersion: null })]), null);
105});
106
107test("the newest security update wins", () => {
108 const older = { state: "superseded" as const, target: "4.17.20", branch: null, pull: 3, issue: null, error: null, updatedAt: "2026-10-01T00:00:00Z" };
109 const newer = { ...older, state: "open" as const, target: "4.17.21", pull: 14, updatedAt: "2026-10-02T00:00:00Z" };
110 assert.equal(latestUpdate([vuln({ update: older }), vuln({ update: newer }), vuln()])?.pull, 14);
111 assert.equal(latestUpdate([vuln()]), null);
112});
113
114const row = (over: Partial<AlertActivity>): AlertActivity => ({
115 id: "act_1",
116 alertId: "sec_1",
117 action: "dismissed",
118 actor: "syntaqx",
119 reason: "used_in_tests",
120 comment: "A fixture.",
121 number: null,
122 at: "2026-10-03T00:00:00Z",
123 ...over,
124});
125
126test("a secret's activity starts with when it was found", () => {
127 const entries = alertActivity(secret({ source: "push", status: "blocked", foundBy: "ana" }), [
128 row({}),
129 row({ id: "act_2", alertId: "sec_other" }),
130 ]);
131 assert.deepEqual(
132 entries.map((e) => [e.actor, e.text]),
133 [
134 ["ana", "pushed it, and the push was refused"],
135 ["syntaqx", "dismissed it"],
136 ],
137 );
138 assert.equal(entries[1].reason, "used_in_tests");
139});
140
141test("an older decision without a row is shown from the alert itself", () => {
142 const entries = alertActivity(
143 secret({ status: "allowed", state: "dismissed", decidedBy: "ana", decidedAt: "2026-10-02T00:00:00Z", reason: "Docs example." }),
144 [],
145 );
146 assert.equal(entries.length, 2);
147 assert.equal(entries[0].text, "Found in the history");
148 assert.equal(entries[0].actor, null);
149 assert.deepEqual([entries[1].actor, entries[1].comment, entries[1].reason], ["ana", "Docs example.", "false_positive"]);
150 // A row for the dismissal replaces it.
151 const covered = alertActivity(
152 secret({ status: "allowed", state: "dismissed", decidedBy: "ana", decidedAt: "2026-10-02T00:00:00Z" }),
153 [row({ actor: "ana" })],
154 );
155 assert.equal(covered.filter((e) => e.text === "dismissed it").length, 1);
156});
157
158test("a dependency's activity links its pull request and issue", () => {
159 const entries = alertActivity(vuln({ state: "fixed", status: "fixed", fixedAt: "2026-10-05T00:00:00Z" }), [
160 row({ id: "a", alertId: "vul_1", action: "update_opened", actor: "g1t", reason: null, comment: null, number: 14, at: "2026-10-02T00:00:00Z" }),
161 row({ id: "b", alertId: "vul_1", action: "update_needs_code", actor: "g1t", reason: null, comment: null, number: 15, at: "2026-10-03T00:00:00Z" }),
162 row({ id: "c", alertId: "vul_1", action: "update_merged", actor: "g1t", reason: null, comment: null, number: 14, at: "2026-10-04T00:00:00Z" }),
163 ]);
164 assert.deepEqual(
165 entries.map((e) => e.ref),
166 [null, { kind: "pull", number: 14 }, { kind: "issue", number: 15 }, { kind: "pull", number: 14 }],
167 );
168 // A merged update already says it was fixed.
169 assert.ok(!entries.some((e) => e.text === "found it no longer vulnerable"));
170});