Many teams thought they were done with Log4Shell the moment they upgraded to the first patched release, only to learn that two further CVEs were waiting. Understanding CVE-2021-45046 and CVE-2021-45105 is what separates a team that patched once and stayed safe from one that patched, relaxed, and remained exposed. This article explains both follow-on flaws for defenders: what each one is, which versions they affect, how they differ in severity, and why 2.17.1 became the version everyone settled on.

To check exactly which of these issues a given build is exposed to, use the Log4j version checker as you read.

Setting the Scene: The Original Flaw

The story starts with CVE-2021-44228, the original Log4Shell remote code execution flaw rated CVSS 10.0, affecting Log4j 2.0-beta9 through 2.14.1. The background on that flaw is covered in what is Log4Shell. The first fix shipped in 2.15.0, which changed the default behaviour so that JNDI lookups were restricted. The problem was that the fix turned out to be incomplete, which is where CVE-2021-45046 enters.

CVE-2021-45046: The Incomplete Fix

CVE-2021-45046 describes the fact that the 2.15.0 fix did not fully close the door. In certain non-default configurations, the protections in 2.15.0 could still be circumvented. Initially this was thought to be only a denial-of-service concern, but it was later reassessed as more serious, because under specific conditions it could permit information leakage and, in some setups, more than just a crash. The practical message for defenders is blunt: 2.15.0 is not a safe stopping point. Upgrading from a vulnerable 2.14.1 to 2.15.0 reduced risk but did not eliminate it. For defenders, the cleanest mental model is to treat 2.15.0 as a partial, transitional release rather than a destination, and to plan from the outset to land on the final recommended version instead of pausing on the first fix that became available.

This is exactly why the guidance in is my Log4j version vulnerable warns that "newer than 2.14.1" is not the same as "safe." The fix that fully addressed CVE-2021-45046 came in 2.16.0, which went further by disabling message lookups entirely and removing JNDI support by default.

CVE-2021-45105: The Denial-of-Service Follow-Up

With 2.16.0 widely deployed, a third issue emerged: CVE-2021-45105. This one is a denial-of-service flaw rather than a remote code execution flaw. It involved Log4j not protecting against uncontrolled recursion in certain self-referential lookup patterns, which could lead to a stack overflow and crash the application under specific configurations. It is meaningfully less severe than the original RCE, but it still mattered because an attacker could potentially knock a service offline.

CVE-2021-45105 was addressed in 2.17.0. Shortly after, a further, more narrowly scoped issue affecting the JDBC Appender (CVE-2021-44832) led to 2.17.1, which became the recommended release for Java 8 and above.

The Two CVEs Side by Side

Holding the differences clearly in mind helps you communicate risk accurately:

  • CVE-2021-45046: the incomplete fix in 2.15.0; reassessed upward in severity; could go beyond denial of service in certain non-default configurations; resolved in 2.16.0.
  • CVE-2021-45105: a denial-of-service flaw from uncontrolled recursion in self-referential lookups; affects up to and including 2.16.0; resolved in 2.17.0.
  • Severity: 45046 is the more serious of the two; 45105 is a crash-class issue, lower impact but still worth fixing.
  • Safe endpoint: only 2.17.1 (or the 2.12.4 and 2.3.2 backports) clears all of these plus the later JDBC Appender issue.

Why Teams Got Caught Out

The follow-on CVEs caught defenders for a predictable reason: emergency patching rewards speed, and the first available fix felt like the finish line. Several factors compounded the confusion:

  1. The fix shipped in stages. 2.15.0, then 2.16.0, then 2.17.0, then 2.17.1, each closing a different issue.
  2. Severity was reassessed. CVE-2021-45046 was initially scored low and later raised, so teams who acted on the first score under-prioritised it.
  3. Different flaw classes. Mixing an RCE and a DoS in the same saga made it easy to conflate "patched against RCE" with "fully safe."
  4. Bundled software lag. Vendor products often shipped intermediate versions, so an estate could be a patchwork of 2.15, 2.16, and 2.17 at once.

The defensive takeaway is to anchor on the final recommended version rather than any intermediate one. The complete ordering is laid out in the Log4j patch timeline.

What This Means for Your Remediation

If your remediation target was anything earlier than 2.17.1, revisit it. A host on 2.15.0 still carries 45046 and 45105; a host on 2.16.0 still carries 45105. Neither is an acceptable resting state. Re-run the version checker against every instance and confirm it reports 2.17.1 or later, or the appropriate backport. The mechanics of forcing that version across transitive and bundled copies are covered in how to patch Log4j.

Prioritising Among the Three CVEs

If you must triage with limited time, weight by impact. The original CVE-2021-44228 and the reassessed CVE-2021-45046 are the ones that can lead to code execution or worse, so any host exposed to those takes precedence. CVE-2021-45105, being a denial-of-service flaw, is important but ranks below the code-execution issues for an internet-facing system handling untrusted input. That said, the simplest and least error-prone strategy is to drive everything to 2.17.1 in one move, which clears all three at once and removes the need to reason about each host's exact exposure.

Keep Detection Running Regardless

Whichever version a host lands on, keep your detections live. The log and network hunting described in detecting Log4Shell in logs remains valuable, because it tells you whether a host was probed during the window before it reached a safe version. Patching and detection are complementary: one closes the path, the other tells you whether it was used. Running both in parallel is what gives a complete picture: the version state tells you your forward exposure, while the historical hunt tells you whether the window before you patched was ever abused.

Explaining the CVEs to Stakeholders

Part of handling these follow-on flaws is communicating them clearly to people who are not steeped in the detail. A simple framing helps: there was one critical remote code execution flaw, an incomplete first fix that turned out to be more serious than initially scored, and a less severe denial-of-service issue, all resolved by landing on a single recommended version. Stakeholders rarely need the per-CVE minutiae; they need to know that stopping at an intermediate version leaves the organisation exposed and that the plan is to reach the final safe release everywhere. Framing it this way avoids both panic and complacency, and it justifies the effort of chasing every host to the recommended version rather than settling for the first patch that appeared to work.

Why the Severity Reassessment Mattered

The upward reassessment of CVE-2021-45046 is a reminder that an initial severity score is a starting estimate, not a final verdict. Teams that acted only on the first low score under-prioritised the issue and were caught out when it was raised. The defensive lesson is to track advisories over time and revisit decisions when scores change, rather than treating the first published number as settled fact.

Conclusion

CVE-2021-45046 was the incomplete-fix flaw in 2.15.0, more serious than first thought and resolved in 2.16.0; CVE-2021-45105 was a denial-of-service follow-up resolved in 2.17.0. Because the fix arrived in stages, only 2.17.1 (or the 2.12.4 and 2.3.2 backports) clears everything. Confirm each instance with the version checker at log4shell.tools and make 2.17.1 your single remediation target.