Skip to content

fix(ui): security and crash fixes for findings grouped view#10514

Merged
alejandrobailo merged 1 commit intofix/ui-findings-groups-improvementsfrom
fix/ui-findings-groups-security-fixes
Mar 31, 2026
Merged

fix(ui): security and crash fixes for findings grouped view#10514
alejandrobailo merged 1 commit intofix/ui-findings-groups-improvementsfrom
fix/ui-findings-groups-security-fixes

Conversation

@Alan-TheGentleman
Copy link
Copy Markdown
Contributor

🔗 Part of Chained PRs

Field Value
Feature Branch fix/ui-findings-groups-improvements
Main PR #10513
Chain Position 1 of 4

Chain Overview

         ┌──────────────────────────┐
         │ 📍 #THIS: Security &     │
         │    crash fixes           │
         └────────────┬─────────────┘
                      │
           ┌──────────┴──────────┐
           │                     │
           ▼                     ▼
  ┌─────────────────┐  ┌─────────────────┐
  │ PR #2: Code     │  │ PR #3: Pepe     │
  │ quality         │  │ blockers        │
  └────────┬────────┘  └────────┬────────┘
           │                    │
           └────────┬───────────┘
                    ▼
           ┌─────────────────┐
           │ PR #4: Pepe UX  │
           └────────┬────────┘
                    ▼
           ┌─────────────────┐
           │ #10513 Main PR  │
           │   → master      │
           └─────────────────┘

Context

Post-merge security and crash fixes for the findings grouped view (PR #10425 by @alejandrobailo). Issues were identified through adversarial code review (Judgment Day protocol with 2 independent blind judges).


Description

5 fixes, 26 tests (17 new), implemented with Strict TDD (Red → Green → Triangulate → Refactor):

  1. SSRF/path traversalcheckId was interpolated directly into URL paths without encoding. Added encodeURIComponent(checkId) in both getFindingGroupResources and getLatestFindingGroupResources. Tests cover: normal IDs, path traversal (../../admin), URL-encoded slashes (%2F), and query/fragment injection (?, #).

  2. SSR crashcreatePortal(_, document.body) was called unconditionally, crashing during server-side rendering where document is undefined. Added isMounted state guard with useEffect. Tests verify portal is NOT called synchronously (before effects fire) and IS called after mount.

  3. Invalid Tailwindmt-[-10] has no unit, so Tailwind 4 generates no CSS (broken layout). Replaced with -mt-2.5 (10px in Tailwind's 4px scale). Test asserts correct class and absence of invalid class.

  4. Unbounded page[size]page[size] was set to resourceUids.length with no cap. Added Math.min(length, 500) as defense-in-depth alongside existing chunking. Tests verify: boundary (500), over-cap (501→split into [500,1]), and under-cap (3).

  5. pageRef race conditionloadNextPage incremented pageRef.current before fetchPage, causing permanent page skip if abort fired concurrently. Moved increment inside fetchPage after successful response. Removed redundant pageRef.current = 1 pre-set from refresh(). Tests verify: race between refresh and loadNextPage, sequential page ordering.

TDD Cycle Evidence

Fix Test File Safety Net RED GREEN TRIANGULATE
SSRF finding-groups.test.ts N/A (new) ✅ 4 failed ✅ 6/6 /, %2F, ?#, normal
SSR inline-resource-container.test.tsx N/A (new) ✅ Written ✅ 4/4 ✅ 3 guard tests
Tailwind inline-resource-container.test.tsx N/A (new) ✅ Failed ✅ 4/4 ✅ +/- assertions
page[size] findings-by-resource.test.ts ✅ 4/4 ✅ Failed ✅ 7/7 ✅ boundary, cap, chunk
pageRef use-infinite-resources.test.ts ✅ 7/7 ✅ Written ✅ 9/9 ✅ race, sequence

Judgment Day: 3 rounds of adversarial review (6 judge delegations). Round 1 caught false-positive tests. Round 2 caught TypeScript error + "use server" export issue. Round 3: both judges CLEAN.


Steps to review

  1. Check finding-groups.test.ts — verify SSRF test cases cover the attack vectors
  2. Check inline-resource-container.test.tsx — verify createPortal spy correctly tests the SSR guard
  3. Check use-infinite-resources.test.ts — verify race condition test setup
  4. Run cd ui && pnpm vitest run actions/finding-groups/finding-groups.test.ts actions/findings/findings-by-resource.test.ts components/findings/table/inline-resource-container.test.tsx hooks/use-infinite-resources.test.ts — all 26 should pass

Checklist

Community Checklist
  • This feature/issue is listed in here or roadmap.prowler.com
  • Is it assigned to me
  • Review if the code is being covered by tests.
  • Review if backport is needed. — No
  • Review if is needed to change the Readme.md — No

UI

  • All issue/task requirements work as expected on the UI
  • Ensure new entries are added to ui/CHANGELOG.md — Will be in Main PR

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

- Fix SSRF path traversal: encode checkId with encodeURIComponent in
  getFindingGroupResources and getLatestFindingGroupResources URL paths
- Fix SSR crash: add isMounted guard for createPortal(document.body) in
  InlineResourceContainer to prevent document access during server render
- Fix invalid Tailwind: replace mt-[-10] (no unit) with -mt-2.5 scale token
- Fix unbounded page[size]: cap at 500 via Math.min in URL builder as
  defense-in-depth alongside existing chunking
- Fix pageRef race condition: move page counter increment inside fetchPage
  after successful non-aborted response, remove redundant pre-set from
  refresh() to prevent permanent page skip on concurrent abort

26 tests across 4 test suites (2 new, 2 extended). All passing.
TypeScript: 0 errors in changed files. ESLint: 0 errors.
Claude Code validation: PASSED.
Pre-existing healthcheck failures (.next/types, @codemirror) unrelated.
@Alan-TheGentleman Alan-TheGentleman requested a review from a team as a code owner March 30, 2026 13:10
@Alan-TheGentleman Alan-TheGentleman added component/ui no-changelog Skip including change in changelog/release notes labels Mar 30, 2026
@Alan-TheGentleman Alan-TheGentleman changed the title [CHAIN] fix(ui): security and crash fixes for findings grouped view fix(ui): security and crash fixes for findings grouped view Mar 30, 2026
Copy link
Copy Markdown
Contributor

@alejandrobailo alejandrobailo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: Approve

Solid security and crash fixes, well-tested with TDD. A couple of observations:

1. pageRef race condition fix is incomplete in isolation

The fix correctly moves pageRef.current = page into fetchPage (post-success) and removes the pre-commit from loadNextPage. However, it also removes pageRef.current = 1 from refresh().

This creates a window where if refresh() is called and the subsequent fetchPage(1, ...) is aborted before completing (e.g., another refresh fires), pageRef.current retains its previous value. Then loadNextPage would calculate the wrong next page.

PR #10515 silently re-adds pageRef.current = 1 in refresh(), which fixes it. But the remove-in-#10514/add-in-#10515 dance is confusing for reviewers. Ideally this should have been complete within this PR.

Not blocking since #10515 fixes it, but worth noting.

2. Duplicate constant

MAX_RESOURCE_FINDING_PAGE_SIZE = 500 is defined alongside the existing FINDING_GROUP_RESOURCES_RESOLUTION_PAGE_SIZE = 500 in findings-by-resource.ts. Same value, same semantic purpose. Consider unifying or documenting why they're separate.

@alejandrobailo alejandrobailo self-assigned this Mar 31, 2026
@alejandrobailo alejandrobailo merged commit 5306bb1 into fix/ui-findings-groups-improvements Mar 31, 2026
1 check passed
@alejandrobailo alejandrobailo deleted the fix/ui-findings-groups-security-fixes branch March 31, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/ui no-changelog Skip including change in changelog/release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants