ADR for feature "Known Exploited Vulnerabilities"#6315
Conversation
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>
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Up to standards ✅🟢 Issues
|
|
|
||
| #### 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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 throughVULNERABILITY_ALIASas you noted. - For views / endpoints where more detail is desired, we surface all assertions, including their data like
published/dateAdded/dueDateetc.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
There was a problem hiding this comment.
I am asking around if we can get any at least semi-official info from ENISA or ENISA-adjacent folks on this.
There was a problem hiding this comment.
Ah-ha! There is a dedicated feed with custom data here: https://github.com/enisaeu/CNW/tree/main/advisories/eukev
There was a problem hiding this comment.
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.
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. |
There was a problem hiding this comment.
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 throughVULNERABILITY_ALIASas you noted. - For views / endpoints where more detail is desired, we surface all assertions, including their data like
published/dateAdded/dueDateetc.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>
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>
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
Checklist
docs/adr/