Skip to content

Commit 0e64263

Browse files
fix(alert detected type): don't default to leaked secret (#208)
* rename timestamp coloumn to time * make 'time' the first column * use relative date time format in alerts table * rename trigger type column to type * clamp trigger markdown to a single lineoverflowoverflow * remove code and file columns from alerts table * rename trigger token column to event * . * implement event column content correctly * implement type column values * add note about ongoing discussion on message type * fix mapping alerts type * display detected problem properly * configure alerts table width * fix(getIssueDetectedType): don't default to `leaked_secret` * fix(`AlertsTable`): failing test * chore: tidy up * fix table column sizing using <ResizableTableContainer /> --------- Co-authored-by: Daniel Kantor <[email protected]>
1 parent 97bc4ea commit 0e64263

File tree

8 files changed

+121
-7
lines changed

8 files changed

+121
-7
lines changed

src/components/AlertsTable.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ function IssueDetectedCellContent({ alert }: { alert: AlertConversation }) {
7070
return (
7171
<>
7272
<PackageX className="size-4 text-blue-700" />
73+
7374
Blocked malicious package
7475
</>
7576
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { test, expect } from "vitest";
2+
import { isAlertMalicious } from "../is-malicious";
3+
import { ALERT_MALICIOUS } from "../../mocks/alert-malicious.mock";
4+
import { ALERT_SECRET } from "../../mocks/alert-secret.mock";
5+
6+
test("matches malicious alert", () => {
7+
expect(isAlertMalicious(ALERT_MALICIOUS)).toBe(true);
8+
});
9+
10+
test("doesn't match secret", () => {
11+
expect(isAlertMalicious(ALERT_SECRET)).toBe(false);
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { test, expect } from "vitest";
2+
import { ALERT_MALICIOUS } from "../../mocks/alert-malicious.mock";
3+
import { ALERT_SECRET } from "../../mocks/alert-secret.mock";
4+
import { isAlertSecret } from "../is-alert-secret";
5+
6+
test("matches secret alert", () => {
7+
expect(isAlertSecret(ALERT_SECRET)).toBe(true);
8+
});
9+
10+
test("doesn't match malicious", () => {
11+
expect(isAlertSecret(ALERT_MALICIOUS)).toBe(false);
12+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { AlertConversation } from "@/api/generated";
2+
3+
export function isAlertSecret({
4+
trigger_type,
5+
trigger_category,
6+
}: AlertConversation) {
7+
return trigger_category === "critical" && trigger_type === "codegate-secrets";
8+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { AlertConversation } from "@/api/generated";
2+
3+
export function isAlertMalicious({
4+
trigger_string,
5+
trigger_category,
6+
}: AlertConversation) {
7+
return (
8+
trigger_category === "critical" &&
9+
trigger_string !== null &&
10+
typeof trigger_string === "object" &&
11+
"status" in trigger_string &&
12+
trigger_string.status === "malicious"
13+
);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { AlertConversation, QuestionType } from "@/api/generated";
2+
3+
export const ALERT_MALICIOUS = {
4+
conversation: {
5+
question_answers: [
6+
{
7+
question: {
8+
message:
9+
"Context: invokehttp is a Python package available on PyPI ecosystem. However, this package is found to be malicious and must not be used. For additional information refer to https://www.insight.stacklok.com/report/pypi/invokehttp - Package offers this functionality: Python HTTP for Humans.\n \n\n Query: Is invokehttp a malicious package?",
10+
timestamp: "2025-01-14T16:29:49.602403Z",
11+
message_id: "bf92bf3c-fcec-4064-ad02-c792026c3555",
12+
},
13+
answer: {
14+
message:
15+
"**Warning:** CodeGate detected one or more malicious, deprecated or archived packages.\n- Pkg 1: [https://www.insight.stacklok.com/report/pypi/invokehttp](https://www.insight.stacklok.com/report/pypi/invokehttp)",
16+
timestamp: "2025-01-14T16:29:50.213490Z",
17+
message_id: "7e260699-906e-43dc-a43e-8f288389bd9d",
18+
},
19+
},
20+
],
21+
provider: "copilot",
22+
type: QuestionType.CHAT,
23+
chat_id: "bf92bf3c-fcec-4064-ad02-c792026c3555",
24+
conversation_timestamp: "2025-01-14T16:29:49.602403Z",
25+
},
26+
alert_id: "bf92bf3c-fcec-4064-ad02-c792026c3555",
27+
code_snippet: null,
28+
trigger_string: {
29+
name: "invokehttp",
30+
type: "pypi",
31+
status: "malicious",
32+
description: "Python HTTP for Humans.",
33+
},
34+
trigger_type: "codegate-context-retriever",
35+
trigger_category: "critical",
36+
timestamp: "2025-01-14T16:29:49.602403Z",
37+
} satisfies AlertConversation;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { AlertConversation, QuestionType } from "@/api/generated";
2+
3+
export const ALERT_SECRET = {
4+
conversation: {
5+
question_answers: [
6+
{
7+
question: {
8+
message: "Analyse this file please",
9+
timestamp: "2025-01-13T17:15:06.942856Z",
10+
message_id: "11ab8b11-0338-4fdb-b329-2184d3e71a14",
11+
},
12+
answer: {
13+
message: "foo-bar",
14+
timestamp: "2025-01-13T17:15:08.537530Z",
15+
message_id: "f1a6201f-0d7f-4c93-bb84-525f2a2d0d3b",
16+
},
17+
},
18+
],
19+
provider: "copilot",
20+
type: QuestionType.CHAT,
21+
chat_id: "11ab8b11-0338-4fdb-b329-2184d3e71a14",
22+
conversation_timestamp: "2025-01-13T17:15:06.942856Z",
23+
},
24+
alert_id: "11ab8b11-0338-4fdb-b329-2184d3e71a14",
25+
code_snippet: null,
26+
trigger_string:
27+
"Amazon - Secret Access Key:\n steps:\n - name: Checkout Repository\n uses: REDACTED<$foo-bar> # v4\n\n - name: Setup\n uses: ./.github/actions/setup",
28+
trigger_type: "codegate-secrets",
29+
trigger_category: "critical",
30+
timestamp: "2025-01-13T17:15:06.942856Z",
31+
} satisfies AlertConversation;

src/lib/utils.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { AlertConversation, Conversation } from "@/api/generated/types.gen";
2+
import { isAlertSecret } from "@/features/alerts/lib/is-alert-secret";
3+
import { isAlertMalicious } from "@/features/alerts/lib/is-malicious";
24
import { MaliciousPkgType, TriggerType } from "@/types";
35
import { format, isToday, isYesterday } from "date-fns";
46

@@ -178,12 +180,9 @@ export function getMaliciousPackage(
178180

179181
export function getIssueDetectedType(
180182
alert: AlertConversation,
181-
): "malicious_package" | "leaked_secret" {
182-
const maliciousPackage = getMaliciousPackage(alert.trigger_string);
183+
): "malicious_package" | "leaked_secret" | null {
184+
if (isAlertMalicious(alert)) return "malicious_package";
185+
if (isAlertSecret(alert)) return "leaked_secret";
183186

184-
if (maliciousPackage !== null && typeof maliciousPackage === "object") {
185-
return "malicious_package";
186-
}
187-
188-
return "leaked_secret";
187+
return null;
189188
}

0 commit comments

Comments
 (0)