DependencyTrack / DependencyTrack/dependency-track
Expose matched subject data in policy violation notifications
- Dominant language
- Java
- Stars
- 4.2k
- Forks
- 811
- Avg merge
- 8h 39m
- Merged PRs (30d)
- 237
Description
### Current Behavior
When a policy condition triggers a violation (for example EPSS ≥ 0.5 or a specific severity) a `PolicyViolationSubject` notification is sent. The notification carries the condition configuration (subject, operator, configured threshold value) and the affected component and project, but never the actual data that caused the match.
A recipient cannot tell from the notification alone which CVE, license, or other subject entity triggered the violation. For set-based subjects such as EPSS or SEVERITY, a follow-up API call may not even be deterministic: a component can have multiple vulnerabilities above the threshold, and there is no way to know which one was responsible.
### Proposed Behavior
At notification dispatch time, resolve the matched subject data and include it in both `PolicyViolationSubject` and `NewPolicyViolationsSummarySubject` protos so it is available in notification templates. For example:
- EPSS / SEVERITY / VULNERABILITY_ID / CWE: vulnerability UUID, CVE ID, and the score or severity that satisfied the condition
- LICENSE / LICENSE_GROUP: license name and SPDX ID that matched
- PACKAGE_URL / CPE / COORDINATES / VERSION: the component-level value that matched
The EXPRESSION subject is excluded since there is no single matched entity to resolve.
For set-based subjects like SEVERITY, EPSS, or LICENSE a component can have multiple entities satisfying the condition at the same time (e.g. several vulnerabilities above the EPSS threshold). All matching entities should be included.
It seems like the `NewPolicyViolationsSummary` already does some lookups and at some points all the required info.
This makes notifications self-contained. Recipients can triage a violation without a follow-up API call and downstream integrations (email digests, dashboards, ticketing) do not need N additional calls per violation.
For instance when using `subject.violationsByProjectList` in the summary notification:
```pebble
Condition: {{ violation.policyCondition.subject }} {{ violation.policyCondition.operator }} {{ violation.policyCondition.value }}
{% if violation.matchedVulnerabilitiesList is not empty %}
Matched vulnerabilities:
{% for vuln in violation.matchedVulnerabilitiesList %}
- {{ vuln.vulnId }} (EPSS: {{ vuln.epssScore }}, Severity: {{ vuln.severity }})
{% endfor %}
{% endif %}
```
This would produce something like:
```plain
Condition: EPSS >= 0.5
Matched vulnerabilities:
- CVE-2024-12345 (EPSS: 0.823, Severity: CRITICAL)
- CVE-2024-67890 (EPSS: 0.541, Severity: HIGH)
```
### Checklist
- [x] I have read and understand the [contributing guidelines](https://github.com/DependencyTrack/dependency-track/blob/main/CONTRIBUTING.md#filing-issues)
- [x] I have checked the [existing issues](https://github.com/DependencyTrack/dependency-track/issues) for whether this enhancement was already requested
Contributor guide
Research direction
Start at notification dispatch and inspect the PolicyViolationSubject and NewPolicyViolationsSummarySubject proto definitions, then follow the existing NewPolicyViolationsSummary lookups used by violationsByProjectList. Done means notification templates can access all matching entities for supported subjects, while EXPRESSION remains excluded; verify the example summary data and affected notification paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend-api-design, security
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100