The Java Bugs No Scanner Can See, and What Protects You Instead
On 6 October 2026, IBM and Red Hat announced that Lightwell, their joint open source security initiative, has identified and remediated more than 400 previously unknown vulnerabilities in widely used Java libraries. That figure is the vendors' own claim: the release does not publish a CVE list, and nobody outside the two companies has evaluated it. On the same day, Lightwell Clearinghouse became generally available. It is a commercial service where enterprise customers can submit specific open source dependencies for priority review and get fixes that apply to the older versions they still run.
The number is the least interesting part. What matters for anyone running their own server is the word "unknown". Those bugs had no CVE when they were found, so no scanner, dashboard or Dependabot alert would have shown them to you. That gap is where most real risk sits, and it is what this post is about.
Where self-hosted Java apps hide in a normal stack
Plenty of people tell me they do not run Java. Then they look at docker ps. Jenkins is Java. Keycloak is Java. Elasticsearch and OpenSearch are Java, and so is Graylog, which sits on top of them. SonarQube, Nexus Repository and Kafka all run on the JVM. The web front end of Apache Guacamole runs inside Tomcat, as do many older tools packaged as WAR files.
Each of those apps is a thin layer on top of a deep pile of libraries. There is something for logging, something for parsing JSON and XML, an HTTP client, compression, cryptography, templating, database drivers. Each of those libraries pulls in its own dependencies. A typical Java server app ships with dozens of JAR files, and the bigger ones ship with hundreds.
You can see this for yourself. On most images, this counts the JAR files inside a running container:
docker exec <container> sh -c 'find / -name "*.jar" 2>/dev/null | wc -l'You did not choose any of those libraries. The app's maintainers chose them, and many are bundled inside other JARs where no package manager can see them. Log4Shell in 2021 was the lesson: a lot of people learned they ran Log4j only when the headline arrived.
Why a green scanner means less than you think
Tools like Trivy, Grype and Dependabot do one job well. They read the list of packages and versions in your image or repository, then compare that list against databases of known vulnerabilities. If a match exists, you get a warning. That is useful, and you should keep running them.
But a scanner can only flag what someone has already catalogued. A bug that nobody has reported yet has no CVE, no advisory and therefore no signature. Your scan comes back clean, and clean only means "nothing in the catalogue matches your versions today". It does not mean "no bugs". I made the same point in the earlier post on why reports and scanners are not a security plan.
The vendors' own framing in the announcement is fair here: many tools can identify potential problems, but detection alone does not remove the risk. Even when a scanner does turn red, someone still has to write a fix that works for your version, and you still have to install it. They also argue that autonomous AI agents can chain several lower-risk weaknesses into a more serious attack. Whether or not that plays out at scale, the defence is the same: fewer known holes left open for long.
What backporting means
When maintainers fix a bug, the fix usually lands in the newest version first. Backporting means applying that same small fix to older release lines that are still supported. Instead of jumping from version 2.4 to 3.0, with config changes and database migrations, you move from 2.4.6 to 2.4.7 and get only the fix.
This is what lets an old, stable appliance get patched without planning an upgrade window. Gunnar Hellekson, vice president and general manager of Lightwell at Red Hat, put it this way: "Finding those bugs is only half the battle: the real work is backporting fixes directly into active production apps so customers do not have to pick between security and uptime."
Clearinghouse sells that work to enterprises, delivered through secured repositories that plug into their existing scanners and pipelines. For everyone else, the release says applicable fixes are contributed back to the upstream open source projects under responsible disclosure. So the free path is simple: the fix lands upstream, the maintainers ship it, and you get it by updating. That only works if the version you run is one they still ship fixes for.
What you can actually do this week
- Take an inventory. Run
docker ps --format '{{.Names}} {{.Image}}'and write down every image and tag. Flag anything onlatest, because you do not actually know what version that is. Check when each image was built withdocker image inspect --format '{{.Created}}' <image>, and mark anything older than a year. - Check the Java runtime inside. Run
docker exec <container> java -version. Some images keep Java outside the default path, so check the image docs if the command fails. You want a long-term support release that its vendor still patches, not one that went end of life years ago. - Stay inside a supported release line. Look up the support or end-of-life page for each app. Jenkins has an LTS line. Elastic publishes end-of-life dates for each version. Keycloak moves fast and community fixes generally land in current releases, so falling several majors behind means no fix exists for you at all.
- Make updates cheap. Before every update, take a snapshot. A Proxmox or ZFS snapshot works, or stop the stack and archive the volumes. Pin specific tags in your compose file instead of
latest, so rolling back is a one-line change. Then test a restore once, because an untested backup is a guess. - Update on a schedule, not when something breaks. Pick a day each month and do
docker compose pullanddocker compose up -dapp by app, with a quick check that each one still works. Use a notifier such as Diun to tell you when new tags appear. For stateful apps like Keycloak or Elasticsearch, I prefer a notification over silent auto-updates, because their upgrades can include migrations. My full routine is in the patch routine post. - Follow the maintainers, not the headlines. On GitHub, use Watch, then Custom, and tick Releases for each project you run, and check its Security tab for published advisories. Every GitHub project also has a releases feed at
/releases.atomyou can add to an RSS reader. Jenkins publishes its own security advisories with a mailing list. These channels tell you when a fix exists for your version, which is the moment that matters.
The honest limits
You cannot scan your way out of unknown bugs. A better scanner finds known issues faster, but it will never find the next one before it is catalogued. What shortens your exposure is how quickly you apply a fix once it exists.
Some dependencies are compiled in. If a vulnerable library sits inside a fat JAR or a WAR file, you cannot swap it yourself in any sensible way. Replacing a JAR by hand inside a container is undone by the next pull and can break the app. You wait for the maintainer to rebuild and release, which is another reason to run software that still has an active maintainer.
The 400+ figure is vendor-reported and unverified. There is no public CVE list attached to it yet, so treat it as a sign of the kind of problem, not as a measurement anyone has checked.
A paid priority-remediation service is aimed at enterprises stuck on old versions for contractual or certification reasons. A small self-hoster usually does not have that constraint. You can upgrade, so for you the realistic answer is the boring one: versions with an active maintainer, an update routine that actually runs, and a backup you have tested.
If you would rather not do this alone
If you would rather have someone inventory what your stack is running, check which apps are still inside a supported release line and set up a patch routine you do not have to remember, have a look at the services page. You can also find me on Fiverr: hiteshsaini459 · Upwork: hiteshsaini25.