The Log4Shell response was not a single patch but a series of releases over a few intense weeks, each closing a different issue. For defenders, knowing which version fixed what is the difference between confidently declaring a host safe and accidentally stopping one release too early. This article lays out the Log4j patch timeline in order, explains what each release addressed, and identifies the safe endpoint for each Java runtime. Keep it as a reference when you triage versions across your estate.
To map any specific build to its status as you go, use the Log4j version checker.
The Starting Point: The Vulnerable Range
Before the fixes, the affected range was Log4j 2.0-beta9 through 2.14.1, all exposed to CVE-2021-44228, the critical CVSS 10.0 remote code execution flaw described in what is Log4Shell. Any host inside that range running default settings is the highest priority for remediation. Everything in the timeline below is about climbing out of that range to a genuinely safe release. Keeping the sequence straight matters because the fixes arrived quickly and in stages, and during the emergency it was easy to mistake an intermediate release for the finish line. A clear timeline is the antidote to that confusion.
2.15.0: The First, Incomplete Fix
Version 2.15.0 was the initial response. It changed defaults so that JNDI lookups were restricted, which addressed the headline remote code execution scenario in default configurations. However, it was soon found to be incomplete, leading to CVE-2021-45046. In certain non-default configurations the protections could be circumvented, and the severity of that follow-on was later reassessed upward. The practical conclusion for defenders is that 2.15.0 is not a safe stopping point, even though it is newer than the original vulnerable range.
2.16.0: Lookups and JNDI Disabled by Default
Version 2.16.0 went further. It removed the message-lookup feature entirely and disabled JNDI support by default, which fully addressed CVE-2021-45046. This was a much stronger position, but it still was not the end. A separate denial-of-service issue, CVE-2021-45105, remained, involving uncontrolled recursion in certain self-referential lookup patterns that could crash an application. So 2.16.0, while a major improvement, is still not the recommended endpoint. The distinction between these two follow-on CVEs is covered in CVE-2021-45046 vs 45105.
2.17.0: The Denial-of-Service Fix
Version 2.17.0 addressed CVE-2021-45105, resolving the recursion-driven denial-of-service issue. At this point the three headline issues, the original RCE, the incomplete-fix flaw, and the DoS, were all addressed. For a brief period 2.17.0 looked like the finish line.
2.17.1: The Recommended Endpoint
Shortly afterward, a further and more narrowly scoped issue affecting the JDBC Appender was identified, tracked as CVE-2021-44832. It required specific conditions to exploit and was less severe than the earlier flaws, but it led to version 2.17.1, which became the recommended release for Java 8 and above. This is the version to aim for; stopping earlier leaves at least one open issue.
The Backports for Older Java
Not every system runs a current Java version, so the project produced backports that carry the equivalent fixes for older runtimes:
- 2.12.4: the backport for Java 7, carrying the equivalent protections for that runtime.
- 2.3.2: the backport for Java 6, for the oldest supported environments.
If you cannot move to Java 8, these backports are how you reach a safe state without changing your runtime. The version checker recognises them, so you can confirm a backport is in place with the version checker.
The Timeline at a Glance
Holding the sequence in order makes triage fast. Walk it from the top until you reach a host's version:
- 2.0-beta9 to 2.14.1: vulnerable to the original CVE-2021-44228 RCE. Critical.
- 2.15.0: fixes the default RCE case but still affected by CVE-2021-45046 and 45105. Not safe.
- 2.16.0: disables lookups and JNDI by default, fixing 45046, but still affected by CVE-2021-45105. Not safe.
- 2.17.0: fixes the DoS issue 45105, but predates the JDBC Appender fix. Nearly there.
- 2.17.1 and later: the recommended safe endpoint for Java 8 and above.
- 2.12.4 / 2.3.2: safe backports for Java 7 and Java 6 respectively.
Using the Timeline in Practice
The most common mistake the timeline prevents is stopping early. A team that upgraded to 2.15.0 in the first emergency push, then moved on, was left with two open issues. A team that reached 2.16.0 still had the DoS flaw. Anchoring your remediation target on 2.17.1 (or the appropriate backport) means you climb out of the entire saga in one move rather than discovering you need to patch again. The mechanics of forcing that version across transitive and bundled copies are in how to patch Log4j, and the reasoning behind treating intermediate versions as unsafe is in is my Log4j version vulnerable.
Verifying Where Each Host Sits
Because an estate often ends up as a patchwork of intermediate versions, especially when vendor products ship their own builds, verify rather than assume. Feed each discovered version into the version checker to place it precisely on this timeline, and use the Log4Shell scanner to confirm the live behaviour on services where you cannot read the version directly. The combination tells you exactly which step of the timeline each host has reached and how far it still has to climb. Because the same estate frequently contains several different intermediate versions at once, especially where vendor products ship their own bundled builds, the only reliable approach is to assess each host individually against the timeline rather than assuming a single organisation-wide state.
Why the Staged Rollout Happened
It is worth understanding why the fix took several releases, because it explains the confusion that followed. Each release addressed the most pressing issue known at the time, and as researchers scrutinised the patched code, further weaknesses came to light. The first fix restricted the dangerous behaviour, the next removed it more thoroughly, and later releases closed a denial-of-service path and a narrower appender issue. This is a normal pattern when a high-profile vulnerability attracts intense attention: the initial patch is necessary but rarely the last word. For defenders, the practical consequence is to anchor on the final recommended version rather than chasing each intermediate release, which is why driving everything to 2.17.1 or the appropriate backport in a single move is the least error-prone strategy. Acting fast on an intermediate version during the first emergency was reasonable, but those hosts then needed a second upgrade, so any remediation record showing a stop at 2.15.0, 2.16.0, or 2.17.0 should be treated as unfinished work.
Putting the Timeline to Work
The value of the timeline is realised when you map your real hosts onto it and act on where they sit. For each system, record the discovered version, the timeline step it represents, the issues still open at that step, and the single recommended target. A host on 2.14.1 needs the full upgrade and a log hunt for possible exploitation; a host on 2.16.0 only carries the residual denial-of-service issue but still needs to move; a host already on 2.17.1 simply needs periodic re-verification to guard against regression. Driving every system to the recommended endpoint in one planned move, rather than chasing each intermediate release as it appeared, is both faster and less error-prone. Combine this with continuous scanning so that a redeploy which reintroduces an old artifact is caught quickly and the host is returned to its proper place on the timeline.
Conclusion
The Log4j patch timeline runs 2.15.0 (incomplete), 2.16.0 (lookups and JNDI off, still DoS-exposed), 2.17.0 (DoS fixed), and 2.17.1 (the recommended endpoint), with 2.12.4 and 2.3.2 as backports for older Java. The lesson is to target 2.17.1 directly and not stop early. Place each of your hosts on the timeline with the version checker at log4shell.tools.