diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index be12653904..9a83d91fea 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -4,14 +4,18 @@ All notable changes to the **Prowler UI** are documented in this file. ## [1.24.1] (Prowler v5.24.1) -### 🔒 Security - -- Upgrade React to 19.2.5 and Next.js to 16.2.3 to mitigate CVE-2026-23869 (React2DoS), a high-severity unauthenticated remote DoS vulnerability in the React Flight Protocol's Server Function deserialization [(#10754)](https://github.com/prowler-cloud/prowler/pull/10754) - ### 🐞 Fixed - Findings and filter UX fixes: exclude muted findings by default in the resource detail drawer and finding group resource views, show category context label (for example `Status: FAIL`) on MultiSelect triggers instead of hiding the placeholder, and add a `wide` width option for filter dropdowns applied to the findings Scan filter to prevent label truncation [(#10734)](https://github.com/prowler-cloud/prowler/pull/10734) - Findings grouped view now handles zero-resource IaC counters, refines drawer loading states, and adds provider indicators to finding groups [(#10736)](https://github.com/prowler-cloud/prowler/pull/10736) +- Other Findings for this resource: ordering by `severity` [(#10778)](https://github.com/prowler-cloud/prowler/pull/10778) +- Other Findings for this resource: show `delta` indicator [(#10778)](https://github.com/prowler-cloud/prowler/pull/10778) +- Compliance: requirement findings do not show muted findings [(#10778)](https://github.com/prowler-cloud/prowler/pull/10778) +- Latest new findings: link to finding groups order by `-severity,-last_seen_at` [(#10778)](https://github.com/prowler-cloud/prowler/pull/10778) + +### 🔒 Security + +- Upgrade React to 19.2.5 and Next.js to 16.2.3 to mitigate CVE-2026-23869 (React2DoS), a high-severity unauthenticated remote DoS vulnerability in the React Flight Protocol's Server Function deserialization [(#10754)](https://github.com/prowler-cloud/prowler/pull/10754) --- diff --git a/ui/actions/findings/findings-by-resource.test.ts b/ui/actions/findings/findings-by-resource.test.ts index 3a045d2e75..7bc2793195 100644 --- a/ui/actions/findings/findings-by-resource.test.ts +++ b/ui/actions/findings/findings-by-resource.test.ts @@ -272,7 +272,7 @@ describe("getLatestFindingsByResourceUid", () => { handleApiResponseMock.mockResolvedValue({ data: [] }); }); - it("should exclude muted findings by default and always apply severity/time sorting", async () => { + it("should restrict to FAIL, exclude muted findings, and apply severity/time sorting by default", async () => { fetchMock.mockResolvedValue(new Response("", { status: 200 })); await getLatestFindingsByResourceUid({ @@ -284,8 +284,12 @@ describe("getLatestFindingsByResourceUid", () => { expect(calledUrl.searchParams.get("filter[resource_uid]")).toBe( "resource-1", ); + // Status filter is applied server-side so the page[size]=50 window + // always holds FAIL rows — guards against PASS-heavy resources + // starving FAILs out of the result. + expect(calledUrl.searchParams.get("filter[status]")).toBe("FAIL"); expect(calledUrl.searchParams.get("filter[muted]")).toBe("false"); - expect(calledUrl.searchParams.get("sort")).toBe("-severity,-updated_at"); + expect(calledUrl.searchParams.get("sort")).toBe("severity,-updated_at"); }); it("should include muted findings only when explicitly requested", async () => { @@ -297,7 +301,8 @@ describe("getLatestFindingsByResourceUid", () => { }); const calledUrl = new URL(fetchMock.mock.calls[0][0]); + expect(calledUrl.searchParams.get("filter[status]")).toBe("FAIL"); expect(calledUrl.searchParams.get("filter[muted]")).toBe("include"); - expect(calledUrl.searchParams.get("sort")).toBe("-severity,-updated_at"); + expect(calledUrl.searchParams.get("sort")).toBe("severity,-updated_at"); }); }); diff --git a/ui/actions/findings/findings-by-resource.ts b/ui/actions/findings/findings-by-resource.ts index ee6d952cf0..74a0bcb6de 100644 --- a/ui/actions/findings/findings-by-resource.ts +++ b/ui/actions/findings/findings-by-resource.ts @@ -264,8 +264,9 @@ export const getLatestFindingsByResourceUid = async ({ ); url.searchParams.append("filter[resource_uid]", resourceUid); + url.searchParams.append("filter[status]", "FAIL"); url.searchParams.append("filter[muted]", includeMuted ? "include" : "false"); - url.searchParams.append("sort", "-severity,-updated_at"); + url.searchParams.append("sort", "severity,-updated_at"); if (page) url.searchParams.append("page[number]", page.toString()); if (pageSize) url.searchParams.append("page[size]", pageSize.toString()); diff --git a/ui/app/(prowler)/_overview/graphs-tabs/findings-view/findings-view.ssr.tsx b/ui/app/(prowler)/_overview/graphs-tabs/findings-view/findings-view.ssr.tsx index 9554869dce..cca971578c 100644 --- a/ui/app/(prowler)/_overview/graphs-tabs/findings-view/findings-view.ssr.tsx +++ b/ui/app/(prowler)/_overview/graphs-tabs/findings-view/findings-view.ssr.tsx @@ -4,6 +4,7 @@ import { getLatestFindings } from "@/actions/findings/findings"; import { LighthouseBanner } from "@/components/lighthouse/banner"; import { LinkToFindings } from "@/components/overview"; import { ColumnLatestFindings } from "@/components/overview/new-findings-table/table"; +import { CardTitle } from "@/components/shadcn"; import { DataTable } from "@/components/ui/table"; import { createDict } from "@/lib/helper"; import { FindingProps, SearchParamsProps } from "@/types"; @@ -57,24 +58,23 @@ export async function FindingsViewSSR({ searchParams }: FindingsViewSSRProps) { }; return ( -
- Showing the latest 10 new failing findings by severity. -
-+ Showing the latest 10 sorted by severity +
+-
; - } + const name = getResourceData(row, "name"); + const uid = getResourceData(row, "uid"); + const entityAlias = + typeof name === "string" && name.trim().length > 0 && name !== "-" + ? name + : undefined; + const entityId = + typeof uid === "string" && uid.trim().length > 0 && uid !== "-" + ? uid + : undefined; return ( -- {regionText} -
+ + {regionFlag && ( + + {regionFlag} + + )} + {regionText} + ); }, enableSorting: false, diff --git a/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx b/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx index bdc104efbe..bebc9b0c4a 100644 --- a/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx +++ b/ui/components/findings/table/resource-detail-drawer/resource-detail-drawer-content.test.tsx @@ -14,12 +14,14 @@ const { mockWindowOpen, mockClipboardWriteText, mockSearchParamsState, + mockNotificationIndicator, } = vi.hoisted(() => ({ mockGetComplianceIcon: vi.fn((_: string) => null as string | null), mockGetCompliancesOverview: vi.fn(), mockWindowOpen: vi.fn(), mockClipboardWriteText: vi.fn(), mockSearchParamsState: { value: "" }, + mockNotificationIndicator: vi.fn(), })); vi.mock("next/navigation", () => ({ @@ -298,7 +300,11 @@ vi.mock("../delta-indicator", () => ({ })); vi.mock("../notification-indicator", () => ({ - NotificationIndicator: () => null, + NotificationIndicator: (props: Record| + {/* Status */} + |
+ |
+ {/* Finding */}
+
+ |
+ {/* Resource name */}
+
+ |
+ {/* Severity */}
+
+ |
+ {/* Cloud Provider */}
+
+ |
+ {/* Service */}
+
+ |
+ {/* Region */}
+
+ |
+ {/* Time */}
+
+ |
+
|---|