The one finding in 21,075 that attackers already use
On this page
Draugr is an open-source CLI that runs the security scanners a project needs from one file and
ranks their findings by what the project declares, so you know which to fix first. We scanned the
25 most-pulled Docker Official Images, each pinned to the digest its latest tag pointed at on
2026-11-01, with Trivy run through Draugr. Trivy reported 21,075 vulnerabilities across them, one
of them a flaw whose CVE is on CISA's catalog of vulnerabilities known to be exploited and whose
package has a fixed release. We counted it by matching every finding against a copy of the catalog.
Trivy had already rated it critical, the severity a KEV listing raises a finding to, so Draugr's
KEV signal had nothing to add. Draugr's fix list turned the 21,075 into 1,545 actions, and 131 upgrades among
them clear every finding that has a fix published.
The sample
The images are Docker Hub's official images in order of pulls on 2026-11-01, taken in rank order
until 25 were in. Three of the top 28 were left out, hello-world because it carries no software
of its own, and openjdk and centos because Docker Hub marks both deprecated. Each image was
scanned as library/<name>:latest for linux/amd64, pinned by digest, and each digest is listed
under Images.
A finding is one vulnerability in one package version in one image, counted once when the scanner reports it twice. Of the 25 images, 23 produced at least one finding. 20,515 of the findings are in operating-system packages and 560 in language packages such as Go modules, npm packages and Python wheels.
What KEV and EPSS moved
Draugr reads two exploitability signals when the descriptor turns them on, and each can raise a finding's severity before the ranking reads it.
KEV
CISA's Known Exploited Vulnerabilities catalog. A CVE on it becomes critical, whatever severity the scanner gave it.
EPSS
FIRST's Exploit Prediction Scoring System. A CVE scoring at or above the threshold, 0.5 by default, goes up one severity band.
The KEV and EPSS counts in this post come from our own match of the findings against copies of both feeds, made after the scans.
By that count one finding is on the KEV catalog, CVE-2026-111497, an out-of-bounds write in the
Brotli decoder with a fixed package published. Trivy had already rated it critical at 9.8, the
severity KEV raises a finding to, so Draugr's KEV signal changed nothing in that image's report,
which reads KEV nothing raised. When a scanner rates a listed CVE below critical and the
descriptor turns KEV on, the signal raises the finding straight to critical and marks it ↑ KEV.
One in 21,075 invites the question of what a list that so rarely matches is worth. KEV holds flaws attackers are already using, and one of them in a service that faces the internet is enough to put the business at risk. A KEV check earns its place by naming that one finding when it is there, among twenty thousand that nobody is known to exploit.
Twenty-six findings scored 0.5 or more on the EPSS scores of 2026-10-31, and the KEV finding is one of them. Draugr raised each of the other 25 one band, from low to medium, which moves it from P3 to P2. All 25 come from two CVEs, in packages whose distribution has published no fixed release.
WAIT FOR A RELEASE
draugr scan --view actions · 25 reports summedlinux-libc-dev is the Linux kernel's headers package. Trivy matches the kernel's CVEs to it, and none of the 929 in each image has a fixed release.
In each of the ten images that carry one of these findings, the actions holding them head the Wait for a release list. A row there reads Replace or accept, and the image's owner decides between moving to a base that ships a fixed version and accepting the finding with a reason, which Draugr keeps in the report beside the finding.
The ranking
Draugr ranks each finding P1 to P4 from its severity and two facts the descriptor declares about
the component, its exposure (who can reach it) and its criticality (what the business loses when
it stops). We cannot know how you run these images, so the descriptors declare neither. Draugr
then assumes the worst, ranks each image as public and critical, and says so at the top of
every report.
No component declares exposure or criticality, so every one is read as public and critical.
These bands rank severity alone. `draugr classify` makes them describe this application.
project: image-noise-nginx
config:
exploitability:
kev: cache
epss: cache
maxAge: 0s
controls:
images:
enabled: true
components:
- name: nginx
images:
- image: docker.io/library/nginx:latest
digest: sha256:8e0328743c8e52ead9fac9c198d0893d63cd38e41b1d9ea629e092a8ac229a93
That is the descriptor for the first image in the sample. The other 24 differ only in the name and the digest.
With nothing declared, the bands follow severity and the two signals, and 5,261 findings came out P1, 11,216 P2, 4,598 P3 and none P4. Priority separates findings once a team declares what each component is, and that happens in your own descriptor.
nothing declared, read as public · critical
A high-severity finding is P1. On this sample, every image sat here.
exposure: internal · criticality: important
The same high-severity finding is P3. A nightly batch job reachable only from inside the network lands here, below the edge proxy that shares its base image.
Two lists of work
Draugr turns findings into actions, one per package version to upgrade or replace, and sorts the actions into lists by the kind of work each one is. Summed across the 25 reports, two lists hold every finding.
Findings each list clears
The bars are to scale. 21,075 findings become 1,545 actions, and the 131 upgrades clear every finding that has a fix published.
The 131 upgrades are the work a team can do today. The largest across the sample is
Upgrade stdlib v1.24.6 to v1.26.10, a rebuild with a newer Go toolchain, which clears 236
findings over four images. For an image you pull rather than build, declare it builtBy: upstream
and its upgrade rows become a single action, take a newer image.
A plain draugr scan prints the ranked findings. The lists come from draugr scan --view actions,
from output.view: actions in draugr.config.yaml, or from the HTML report that
-o out/ --report html writes.
Turning the signals on
Neither signal runs unless it is turned on: in the descriptor, under config.exploitability, or for one run with --kev and --epss. Each of the 25
descriptors carried this block.
config:
exploitability:
kev: cache
epss: cache
maxAge: 0s
epssThreshold moves the EPSS cut from 0.5. The EPSS and KEV guide covers
what each signal measures and how to choose a threshold.
Limits
- Each image is its
latesttag on one day. A later digest of the same tag can read differently, and a team running a pinned older tag sees more. - A scanner reports what a package's version says, and says nothing about whether the vulnerable code runs in the way the image is used. No reachability is claimed for images.
- A distribution can state that a CVE does not affect its build. Trivy reads those statements, so their findings are already left out of the counts above.
Images
| Rank | Image | linux/amd64 digest |
|---|---|---|
| 1 | library/nginx:latest | sha256:8e0328743c8e52ead9fac9c198d0893d63cd38e41b1d9ea629e092a8ac229a93 |
| 2 | library/memcached:latest | sha256:a433b62b243c3c5be2ce9ec535e4f6d07444fde28af84a4d6231136eb711e8ed |
| 3 | library/busybox:latest | sha256:f97baa533a26513c453a362be331a43eb60214302f449c16571b23cea141dce4 |
| 4 | library/alpine:latest | sha256:c26612752c78b18faacd63c7d50f4592c2e7b0f25e0e20e82bd74e465c57ab0d |
| 5 | library/postgres:latest | sha256:f4b419e350fd98d4a8429603295208976dea4c8fb8326d818d346d3e29f1db6f |
| 6 | library/redis:latest | sha256:10b9c2c0711fdeb667f4bcbf5b1175d9dc926674479c9c9f83d7675e98cd89cb |
| 7 | library/ubuntu:latest | sha256:157dc3d6e4a3e4f2c68d12df9df9ed6e808b59af6d4c3757b432b4f519916725 |
| 8 | library/python:latest | sha256:c6ecb2f3c3dc85a75350f36560e1f49d35d6a9f7ce11fd775bd6834a69a9a0e1 |
| 9 | library/node:latest | sha256:6c6f2679f5b655c7c6091a34b81372b5962ca9f25d897a501d613742f922567b |
| 10 | library/mysql:latest | sha256:633e1a8f622f84e9dbd604ab0be4b95211f9f153fdb9832a47c54982d2d43c54 |
| 11 | library/mongo:latest | sha256:ce91889f87a369d312e50ecbc6c0b7f960e915bc4b69c4f6662402fa7011d242 |
| 12 | library/httpd:latest | sha256:c492904b9367e83e16e0e8c0a3175b0bb97b861023a17dcdfd09cd4c8b6efd9f |
| 13 | library/rabbitmq:latest | sha256:184d4ae2a5d7fd4cbe1ad7165d1fb6c1377735ed2744c6be478deed5e8f0ba88 |
| 14 | library/docker:latest | sha256:97545b7bab66319a476800a85b008b25c06681733d484909e2a776281e41574f |
| 15 | library/traefik:latest | sha256:c999a937a1bb51ba36c79adf2c9db1d1bb196896b66d524d30ef4945606d565f |
| 17 | library/mariadb:latest | sha256:0231965d72f758adea93162ed7be119dfd49f14172c5754ed8c9d49b0f17bbc6 |
| 18 | library/golang:latest | sha256:5bbe76a31abbe0f1449d7820e550131c020b097c24d3bcfc5ad1231779982c1c |
| 20 | library/registry:latest | sha256:1290056e2357eceb0c047cb60ae9abb370305a218e2df650eb8d3ea021b1c151 |
| 21 | library/debian:latest | sha256:e2914ec98e08b24b4cee3cefcb9f90dfb5519f8d215a2ccf0c9a49b10b6e43de |
| 22 | library/ruby:latest | sha256:b3960beab0be58abe7af71f17cb5062a40ee34a8d73c7018f902b53e89e8cd5a |
| 23 | library/wordpress:latest | sha256:fe2f14897f8f46d61d452139aaa5c9359c277256dda69810c96509ad32f273d5 |
| 24 | library/php:latest | sha256:35fd7ee3ab5af1ed1f23f6bb01a3464c10ad0bb813a020b29b770115b852d06f |
| 25 | library/sonarqube:latest | sha256:bf10a99dd098e5f9005f194100b7301fb938650833ec3b07b92e81c327a03b36 |
| 27 | library/haproxy:latest | sha256:8a6a33410486f730298507a199f85618d110de7d28710047701d0739ddd4f0bf |
| 28 | library/influxdb:latest | sha256:a66a9e8b2c93f58bec088c17ff5876540caa095436df5a66e908bdbdb6a36205 |
Rank is the image's place in Docker Hub's pull ranking on 2026-11-01. Ranks 16, 19 and 26 are the three images left out.
Your image
Save this as my-image.saga.yaml, with your own image in place of nginx. It turns on the images
control and both signals.
project: my-image
config:
exploitability:
kev: cache
epss: cache
controls:
images:
enabled: true
components:
- name: my-image
images:
- image: docker.io/library/nginx:latest
Then install Draugr and Trivy, fetch the feeds and scan.
curl -fsSL https://draugr.dev/install.sh | sh
draugr tools install trivy
draugr feeds update
draugr scan my-image.saga.yaml --view actions
A finding KEV raised carries ↑ KEV, one EPSS raised carries ↑ EPSS with its score, and the
SIGNALS line of the report counts both.
(Figures from scans on 2026-11-02 with Draugr 0.165.0 and Trivy 0.76.1, the Trivy vulnerability
database of 2026-11-01, KEV catalog 2026.10.30 and EPSS scores of 2026-10-31, both feeds fetched
2026-10-31 23:04 UTC, of images pinned to their digests of 2026-11-01. Each descriptor read both
feeds with cache, which reads the copies draugr feeds update stored and never fetches during a
scan, and maxAge: 0s, which accepts a copy of any age, so every scan read one KEV catalog and one
day's EPSS scores. A finding counts as on KEV when any of its CVE IDs is in the catalog, and its
EPSS score is the highest among its CVE IDs. Its CVE IDs are any CVE in its rule ID, plus the CVE
aliases the Go vulnerability database lists for a GO or GHSA identifier. Images and advisories move
every day, so re-run it rather than trusting the numbers.)