From 615b40f23ca598f21cf4a3e471d646187c092dcc Mon Sep 17 00:00:00 2001 From: frjcomp <107982661+frjcomp@users.noreply.github.com> Date: Tue, 20 Oct 2026 14:36:43 +0000 Subject: [PATCH 1/3] fix(webui): keep large findings sets responsive Batch replay and live rendering, paginate findings, and cache filtering data. Add browser regressions for large result sets and document pagination behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CONTRIBUTING.md | 6 ++ docs/guides/scanning.md | 2 + pkg/webui/server.go | 73 +++++++++++--- pkg/webui/server_browser_test.go | 131 ++++++++++++++++++++++++ pkg/webui/server_browser_test.js | 164 +++++++++++++++++++++++++++++++ pkg/webui/server_test.go | 58 +++++++++++ 6 files changed, 420 insertions(+), 14 deletions(-) create mode 100644 pkg/webui/server_browser_test.go create mode 100644 pkg/webui/server_browser_test.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 11086de2..86d97bc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -90,6 +90,12 @@ make test-e2e-devops make test-e2e-gitea ``` +The Web UI regression tests exercise a real browser with 2,000 findings, including replay, filtering, pagination, CSV export, and live updates. They run automatically with the unit tests when Chromium or Google Chrome is on `PATH`; otherwise the browser test reports a skip. To use a browser installed elsewhere: + +```bash +PIPELEEK_WEBUI_BROWSER=/path/to/chromium go test ./pkg/webui -race -v +``` + ### Linting ```bash diff --git a/docs/guides/scanning.md b/docs/guides/scanning.md index 00320974..08364474 100644 --- a/docs/guides/scanning.md +++ b/docs/guides/scanning.md @@ -39,6 +39,8 @@ Add `--webui` to serve findings in a live web UI while the scan runs. Pipeleek b Below **Live secret findings**, the UI shows the target instance and effective scan flags, including values from configuration and defaults. Credential values such as tokens and cookies are redacted, and credentials, query parameters, and fragments in the target URL are omitted. +Findings are shown newest first, with 100 results per page. Use **Previous** and **Next** to browse large result sets. Severity, type, and search filters apply to all findings, not just the current page, and changing a filter returns to the first page. **Export CSV** exports every matching finding across all pages. Summary counts always cover the full scan. Incoming findings are rendered in batches to keep the controls responsive. + Use `-v` with `--webui` to see debug-level startup details: ```bash diff --git a/pkg/webui/server.go b/pkg/webui/server.go index 1d4909a5..b5e743fb 100644 --- a/pkg/webui/server.go +++ b/pkg/webui/server.go @@ -1,6 +1,7 @@ package webui import ( + "bufio" "crypto/rand" "encoding/csv" "encoding/hex" @@ -238,6 +239,9 @@ var pageTemplate = strings.Join([]string{ " table th:nth-child(6), table td:nth-child(6) { width: 14%; }", " .details-list li, .details-list a { overflow-wrap: anywhere; word-break: break-word; }", " .findings-table-card { overflow: hidden; }", + " .pagination { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: .75rem; margin-bottom: .75rem; }", + " .pagination-actions { display: flex; gap: .5rem; }", + " .control-btn:disabled { opacity: .5; cursor: default; }", " #toast { position: fixed; right: 1rem; bottom: 1rem; background: rgba(42,74,37,.96); color: #fff; padding: .7rem .9rem; border-radius: 999px; font-size: .84rem; box-shadow: 0 8px 20px rgba(0,0,0,.2); opacity: 0; pointer-events: none; transform: translateY(8px); transition: opacity .18s ease, transform .18s ease; z-index: 2000; }", " #toast.visible { opacity: 1; transform: translateY(0); }", " @media (max-width: 720px) { main { padding: 0 .5rem; } .top-nav-inner { padding: .6rem .75rem; } h1 { font-size: 1.6rem; } }", @@ -332,6 +336,10 @@ var pageTemplate = strings.Join([]string{ " ", " ", "
| Severity | Rule | Secret | Type | Details | Time |
|---|