Skip to content

ADR for feature "Known Exploited Vulnerabilities"#6315

Open
LukasChristel wants to merge 19 commits into
DependencyTrack:mainfrom
LukasChristel:main
Open

ADR for feature "Known Exploited Vulnerabilities"#6315
LukasChristel wants to merge 19 commits into
DependencyTrack:mainfrom
LukasChristel:main

Conversation

@LukasChristel

@LukasChristel LukasChristel commented Jun 8, 2026

Copy link
Copy Markdown

Description

Add an ADR to get the feature of reporting known exploited vulnerabilities started.

Addressed Issue

#2267

Additional Details

I am unsure about many aspects in this ADR. Especially the data storage proposal.

Also unclear

  • Should other sources be mentioned in this ADR? (VulnCheck KEV, inthewild.io, GreyNoise, Metasploit, ExploitDB, Nuclei)
  • Remediation due dates are currently not addressed by the ADR

Checklist

  • I have read and understand the contributing guidelines
  • This PR fixes a defect, and I have provided tests to verify that the fix is effective
  • This PR implements an enhancement, and I have provided tests to verify that it works as intended
  • This PR introduces changes to the database model, and I have updated the migration changelog accordingly
  • This PR introduces new or alters existing behavior, and I have updated the documentation accordingly
  • This PR is a substantial change (per the ADR criteria), and I have added an ADR under docs/adr/

Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
@owasp-dt-bot

owasp-dt-bot commented Jun 8, 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.

@codacy-production

codacy-production Bot commented Jun 8, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

Comment thread docs/adr/029-actively-exploited-vulnerability-monitoring.md Outdated
Comment thread docs/adr/029-actively-exploited-vulnerability-monitoring.md Outdated

#### Check for actively exploited vulnerabilities

To check if any vulnerability in the vulnerability-alias-group is actively exploited, other records from `ACTIVELY_EXPLOITED_VULNERABILITY_ASSERTION` need to be joined through the table `VULNERABILITY_ALIAS`. `ACTIVELY_EXPLOITED_VULNERABILITY_ASSERTION` also needs to be queried without joining `VULNERABILITY_ALIAS` in case no alias exists.

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.

How do we handle multiple assertions for the same vuln? "Has at least one assertion" suffices to check whether a vuln is actively exploited, but auxiliary data like "due date" would need to be disambiguated.

Might be worth synthesizing all assertions into a single "concluded" record whenever an assertion is added or removed. The vuln alias mechanism does something like this, where assertions are used to compute alias groups.

@LukasChristel LukasChristel Jun 9, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Multiple assertions for the same vulnerability would each get a row in KEV_ASSERTION. This assumes the same source does not repeat the same vulnerability-id multiple times. That would violate the primary key constraint.
Querying would join through the alias group like ADR-022.

I did not find a good synthesized format. One attempt is listed in the chapter 'Considered alternatives'. Two more attempts here, if you like one of them I'll update the ADR.

Option 1: Always create alias groups

The alias groups from ADR-014 are always created. Even when no alias-identifiers exist. Then it is just a group with only one member.
The table VULNERABILITY_ALIAS gets a new boolean column KNOWN_EXPLOITED. This column needs to be recomputed after every change to KEV_ASSERTION or VULNERABILITY_ALIAS. It makes querying whether any vulnerability in the alias-group has a vulnerability a bit easier. Only the VULNERABILITY_ALIAS table needs to be queried because it contains entries for ALL vulnerabilities.

Option 2: Materialize into KEV table

This option provides a materialized view like ADR-014

Column Type Constraints
ASSERTER TEXT PK
VULN_SOURCE TEXT PK
VULN_ID TEXT PK
ALIAS_ID TEXT PK

This table needs to be recomputed after every change to KEV_ASSERTION or VULNERABILITY_ALIAS.
Recomputing involves that for every entry in KEV_ASSERTION an entry in KEV is created (VULN_ID and ALIAS_ID are the same). If aliases exist, then an additional entry in KEV is created for each alias.

ALIAS_ID is used in queries that want to know if a vulnerability is known to be exploited; ASSERTER, VULN_SOURCE, VULN_ID are the identifiers required to look up more details in table KEV_ASSERTION.

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.

Upon further research, I'd paddle back on my earlier feedback and would align more with your initial proposal. May be re-stating the obvious but just to have it noted down once:

  • We don't materialize, we only record the raw assertions.
  • The signal that matters in most use-cases is simply the boolean "is this actively exploited?", and that can be answered with a simple EXISTS(SELECT 1 FROM "ACTIVELY_EXPLOITED_VULNERABILITY_ASSERTION" ...) subquery, joined through VULNERABILITY_ALIAS as you noted.
  • For views / endpoints where more detail is desired, we surface all assertions, including their data like published / dateAdded / dueDate etc.

Materializing ACTIVELY_EXPLOITED_VULNERABILITY and having it depend on alias relationships would involve significant overhead which I'd like to avoid. As you noted, that would require refreshing the materialization when KEV assertions or aliases change. The latter is in the hot path during vuln analysis.

@LukasChristel LukasChristel Jun 10, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I included your points in the ADR and put the two options from me into 'Considered alternatives'

In making the change I noticed that some sources (EUVD) provide multiple IDs (CVE-*, GHSA-*, EUVD-*) for one KEV.
I guess these sources should then also be an alias asserter and the information should go into the VULNERABILITY_ALIAS_ASSERTION table. Another option would be to create a copy of the entry in KEV_ASSERTION for each identifier. Any thoughts?

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.

For the purpose of KEV I'd say we should flatten it into multiple records.

But looking at the EUVD page you linked, it says Added to CISA KEV: 2026-06-09 00:00. Do you know of the EUVD even publishes its own KEV data, or does it always parrot CISA? In the latter case there'd be zero use in pulling data from the EUVD.

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.

Found this post from VulnCheck: https://www.vulncheck.com/blog/enisa-euvd

Unfortunately, I was disappointed to find that the ENISA EUVD Exploited Vulnerabilities list is merely a subset of CISA’s Known Exploited Vulnerabilities (KEV).

So I guess there is no value in direct EUVD support for KEV.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

In short: I could find some but not many and not a single official post that claim the EUVD will become relevant for DependencyTrack in the very near future.

Mandatory reporting under the EU Cyber Resilience Act starts September 11th 2026 (https://digital-strategy.ec.europa.eu/en/policies/cra-reporting). I expect that from this date on they will have original data as well.
But posts that share this expectation are rare. There is the last paragraph in https://www.itsecurityguru.org/2025/05/14/enisa-launches-european-vulnerability-database-to-bolster-eu-cyber-resilience/ and the last chapter from https://www.aikido.dev/blog/nist-nvd-changes-2026 that support it.

This article claims that data is exchanged between EUVD and NVD but that they don't necessarily have to agree. https://www.infosecurityeurope.com/en-gb/blog/future-thinking/how-to-use-euvd-enisa.html. It mentions the following authoritative sources available to the EUVD

  • Open-source vulnerability databases (such as CVE and NVD)
  • National CSIRT advisories and security alerts
  • Vendor-provided patching and mitigation recommendations
  • Exploitation status indicators showing active abuse in cyber attacks

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.

I am asking around if we can get any at least semi-official info from ENISA or ENISA-adjacent folks on this.

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.

Ah-ha! There is a dedicated feed with custom data here: https://github.com/enisaeu/CNW/tree/main/advisories/eukev

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.

The EUVD has a data dump API at https://euvdservices.enisa.europa.eu/api/kev/dump.

It's a minimal representation of both CISA's and ENISA's KEV data, e.g.:

  {
    "cveId": "CVE-2024-8963",
    "euvdId": "EUVD-2024-49510",
    "vendorProject": "Ivanti",
    "product": "CSA (Cloud Services Appliance)",
    "dateAdded": "2024-09-19",
    "sources": [
      "cisa_kev",
      "eukev_kev"
    ]
  },
  {
    "cveId": "CVE-2021-31166",
    "euvdId": "EUVD-2021-18079",
    "dateAdded": "2022-04-06",
    "sources": [
      "cisa_kev"
    ]
  },

So here we'd need to skip cisa_kev records to prevent stale data from the EUVD overwriting the authoritative and more up-to-date data from CISA's own feed. With that in mind, I'd argue consuming ENISA's data directly and not going through the EUVD is likely the better option.

@nscuro nscuro added the documentation Improvements or additions to documentation label Jun 8, 2026
@nscuro nscuro added this to the 5.x milestone Jun 8, 2026
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>

#### Check for actively exploited vulnerabilities

To check if any vulnerability in the vulnerability-alias-group is actively exploited, other records from `ACTIVELY_EXPLOITED_VULNERABILITY_ASSERTION` need to be joined through the table `VULNERABILITY_ALIAS`. `ACTIVELY_EXPLOITED_VULNERABILITY_ASSERTION` also needs to be queried without joining `VULNERABILITY_ALIAS` in case no alias exists.

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.

Upon further research, I'd paddle back on my earlier feedback and would align more with your initial proposal. May be re-stating the obvious but just to have it noted down once:

  • We don't materialize, we only record the raw assertions.
  • The signal that matters in most use-cases is simply the boolean "is this actively exploited?", and that can be answered with a simple EXISTS(SELECT 1 FROM "ACTIVELY_EXPLOITED_VULNERABILITY_ASSERTION" ...) subquery, joined through VULNERABILITY_ALIAS as you noted.
  • For views / endpoints where more detail is desired, we surface all assertions, including their data like published / dateAdded / dueDate etc.

Materializing ACTIVELY_EXPLOITED_VULNERABILITY and having it depend on alias relationships would involve significant overhead which I'd like to avoid. As you noted, that would require refreshing the materialization when KEV assertions or aliases change. The latter is in the hot path during vuln analysis.

Comment thread docs/adr/029-actively-exploited-vulnerability-monitoring.md Outdated
Comment thread docs/adr/029-actively-exploited-vulnerability-monitoring.md Outdated
Comment thread docs/adr/029-actively-exploited-vulnerability-monitoring.md Outdated

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.

In your PR description you asked:

Should other sources be mentioned in this ADR? (VulnCheck KEV, inthewild.io, GreyNoise, Metasploit, ExploitDB, Nuclei)

My vote would be no for most of them (except VulnCheck KEV).

#2267 (comment) is asking for multiple states like unknown, exploited and exploit code public. I think we should focus on the "actively exploited" signal that KEV is about. Mostly to keep things simple, but also because "exploit code public" is a very different risk from KEV, and it shares almost no properties with its model.

Regarding your question, VulnCheck is the exception to the above because it provides KEV data. The others provide "exploit code public" signals.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

ADR updated. I am leaving this conversation unresolved for now in case anyone wants to chime in.

Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
… vulnerability (KEV)"

Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
@LukasChristel LukasChristel changed the title ADR for feature "Actively Exploited Vulnerabilities" ADR for feature "Known Exploited Vulnerabilities" Jun 10, 2026
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Signed-off-by: LukasChristel <150170899+LukasChristel@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants