Skip to content

Feat/vulnerability audit filter query params - #1722

Open
duderoot wants to merge 3 commits into
DependencyTrack:mainfrom
duderoot:feat/vulnerability-audit-filter-query-params
Open

Feat/vulnerability audit filter query params#1722
duderoot wants to merge 3 commits into
DependencyTrack:mainfrom
duderoot:feat/vulnerability-audit-filter-query-params

Conversation

@duderoot

Copy link
Copy Markdown

Description

Filters on the Vulnerability Audit page are now reflected in the URL, so a filtered view can be bookmarked, shared with a colleague, or restored with the browser's back button. Previously the filter pills kept their state only in component data, so a URL always pointed at the unfiltered view and any selection was lost on reload.

Opening a URL such as

/vulnerabilityAudit/?severity=critical,high&cvssv3From=7&showKevOnly=true

restores those pills and loads the matching results directly.

The mapping is implemented generically in filterPillsMixin, but each view opts in explicitly, so only the two Vulnerability Audit tabs are affected by this change.

Addressed Issue

Related to #1191, which asks for filter state to be expressible in a link. That issue is about the project findings page (/projects/:uuid/findings), which does not use this mixin, so this PR does not close it — it introduces the mechanism that would make resolving it a small follow-up.

Additional Details

Query parameter format

One parameter per filter, named after the filter itself:

Filter type Example
boolean showKevOnly=true (omitted when off)
multi-select severity=critical,high
text search textSearch=log4j&textSearchFields=vulnerability_id,component_name
date range publishDateFrom=2024-01-01&publishDateTo=2024-12-31
numeric range cvssv3From=7&cvssv3To=9.5

Design notes

  • Values from the URL are validated on the way in. Unknown enum values are dropped, numeric bounds are clamped to the filter's range, and malformed dates are ignored. A hand-edited or truncated URL degrades to a narrower filter rather than pushing junk at the API.
  • Writes use replace() rather than push(). Refining a filter is a change to the current view, not a new destination, so adjusting five filters does not leave five entries to step back through. Leaving the page still behaves normally.
  • A restored view costs one request, not two. The table's URL is built in data(), before filters are read from the query string, so hydration rewrites it before the table component is created. Otherwise every bookmark would fire an unfiltered request followed immediately by the real one.
  • The two audit tabs share a single query string. A view therefore only writes the query while its tab pane is visible, and leaves parameters it does not recognise untouched. That way switching tabs preserves the other tab's filters instead of clobbering them.
  • Opt-in per view. PolicyViolationAudit, ComponentSearch and WorkflowRunList share this mixin and are deliberately left unchanged. Extending it to them is a matter of setting filterUrlSync and declaring a type per filter.

Drive-by fix

VulnerabilityAudit.vue discarded the query string when switching tabs, because it compared fullPath (which includes the query) and then pushed a bare path. It now compares path and carries the query along. Without this the feature could not survive a tab switch.

Tests

This repository had no test runner, so the first commit adds Jest with jsdom and @vue/test-utils, exposed as npm test / npm run test-watch / npm run test-coverage, with specs under tests/. Vue SFC compilation is deliberately left out: the code under test is plain JavaScript, so the setup does not depend on vue-jest.

The feature is covered by 35 tests spanning encoding, decoding, rejection of untrusted values, back/forward navigation, and the tab-gating rules. Two bugs were found and fixed while writing them: a numeric range could be dropped when a query object round-tripped in memory rather than through a URL, and the decoder rejected non-string scalars.

Verified manually against a Dependency-Track 5.0.0 API server as well: applying each filter type updates the URL, reloading restores every pill, switching tabs preserves state, back/forward works, and "Clear all" empties the query string.

Checklist

@owasp-dt-bot

owasp-dt-bot commented Jul 31, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@duderoot
duderoot force-pushed the feat/vulnerability-audit-filter-query-params branch from a05dea2 to 6591dd5 Compare August 1, 2026 14:46

@nscuro nscuro left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we find a way to massively trim down the changeset of this PR? 30k lines added / 20k removed is way too much for what this PR aims to implement.

The project had no test runner, so behaviour could only be verified by
hand against a running instance.

Add Jest with jsdom and @vue/test-utils, exposed as `npm test`,
`npm run test-watch` and `npm run test-coverage`. Specs live in `tests/`.

Vue SFC compilation is deliberately left out: the code under test is
plain JavaScript (mixins and shared modules), so the setup avoids
depending on vue-jest.

Generated coverage output is excluded from ESLint and Prettier, which
would otherwise lint the report.

Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
@duderoot
duderoot force-pushed the feat/vulnerability-audit-filter-query-params branch from 6591dd5 to 1777aa9 Compare August 4, 2026 21:19
@duderoot

duderoot commented Aug 5, 2026

Copy link
Copy Markdown
Author

@nscuro I agree with you—maybe it's too much for a single commit. The thing is, we should also start adding some infrastructure for testing. So I'll move the testing setup to a separate branch.

In the long term, the UI tests should give us confidence that changes to the UI don't break other parts of the application. 🙂

…ters

Filter state lived only in component data, so a filtered view could not
be bookmarked, shared or restored with the browser's back button.

Sync the filter pills to the URL query string. The mapping lives in
filterPillsMixin as a table of codecs, one per filter shape:

  boolean       showKevOnly=true            (omitted when off)
  multi-select  severity=critical,high
  text search   textSearch=log4j&textSearchFields=vulnerability_id
  date range    publishDateFrom=2024-01-01&publishDateTo=2024-12-31
  numeric range cvssv3From=7&cvssv3To=9.5

A view opts in with `filterUrlSync` and declares a `type` per filter, so
the other views sharing this mixin are unaffected.

Notes on behaviour:

* Values from the URL are validated on the way in. Unknown enum values
  are dropped, numeric bounds are clamped to the filter's range, and
  malformed dates are ignored, so a hand-edited URL cannot push junk to
  the API.
* Writes use replace() rather than push(), since refining a filter is
  not a separate destination to step back through.
* Filters restored on load rewrite the table's URL before the table is
  created, so a bookmark costs one request instead of two.
* The two audit tabs share one query string, so a view only owns the
  query while its tab pane is visible, and leaves parameters it does not
  recognise untouched.

VulnerabilityAudit dropped the query string when switching tabs, because
it compared fullPath and pushed a bare path. It now compares path and
carries the query along.

Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
This reverts commit 40738c8.

Signed-off-by: duderoot <catalin.patruica@xlab-iq.de>
@duderoot
duderoot force-pushed the feat/vulnerability-audit-filter-query-params branch from 09d7b9b to dee9153 Compare August 5, 2026 23:00
@duderoot

duderoot commented Aug 5, 2026

Copy link
Copy Markdown
Author

Testing with some new test for the existing code was created in the PR for #1722
In this PR I reverted the test infrastructure.

@duderoot
duderoot requested a review from nscuro August 7, 2026 09:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants