Apache Log4j is the most widely deployed logging library in the Java world. Log4j 2 is a direct or transitive dependency of an enormous share of Java applications, embedded through frameworks, application servers, and enterprise software that most teams never think about as "using Log4j." That ubiquity is precisely why the Log4Shell disclosure in December 2021 became the defining supply-chain security event of the decade: a single logging library turned out to allow trivial remote code execution across a staggering number of systems at once. Years later, Log4j remains a top-priority package to inventory and keep patched.
The notable historical CVEs
Log4Shell was not a single CVE but a cluster of four, disclosed in quick succession as fixes were rushed out and bypassed:
- CVE-2021-44228 (Log4Shell) — the original critical (CVSS 10.0) remote code execution. Log4j 2 evaluated JNDI lookups embedded in logged strings, so logging attacker-controlled input like
${jndi:ldap://...}could load and execute remote code. Affected2.0-beta9through2.14.1; first addressed in2.15.0. - CVE-2021-45046 — the
2.15.0fix was incomplete; certain non-default configurations still allowed RCE and denial of service. Fixed in2.16.0. - CVE-2021-45105 — a denial of service via uncontrolled recursion from self-referential lookups in context-map data. Fixed in
2.17.0. - CVE-2021-44832 — remote code execution possible if an attacker could modify the logging configuration to point a JDBC Appender at a malicious source. Fixed in
2.17.1.
Separately, Log4j 1.x is end-of-life and carries its own serious unpatched-by-design issues, including CVE-2019-17571 (deserialization in SocketServer), CVE-2022-23302 (JMSSink deserialization), and CVE-2022-23305 (SQL injection in the JDBC Appender). There is no safe supported version of Log4j 1.x — the only fix is to migrate off it.
Common misuse and risks
- Logging untrusted input. Log4Shell was so devastating because applications log user-controlled data everywhere — headers, usernames, User-Agent strings. The vulnerability lived in message lookups, so any logged attacker string was a potential payload.
- Still running Log4j 1.x. It reached end-of-life in 2015. Teams keep it alive because "it works," but it ships known, unfixable deserialization and injection flaws.
- Hidden transitive copies. Log4j is bundled inside so many artifacts and fat JARs that "we don't use Log4j" is frequently false. Shaded and relocated copies inside vendor software were a huge part of why Log4Shell remediation dragged on for months.
- Partial upgrades. Bumping only to
2.15.0or2.16.0and stopping leaves you exposed to the later DoS and JDBC-appender CVEs.
How to use Log4j safely
Set the version floor: run Log4j 2 at 2.17.1 or later, which fixes all four Log4Shell-era CVEs. Newer 2.x releases are preferred and continue to carry hardening and dependency fixes. For legacy runtimes there were backports (2.12.4 for Java 7, 2.3.2 for Java 6), but the goal should be a current release on a current JVM.
Additional guidance:
- Migrate off Log4j 1.x entirely. Move to Log4j 2 or SLF4J with a maintained backend. There is no patched 1.x to upgrade to.
- Message lookups are disabled by default in fixed versions; do not re-enable them, and never construct log statements that interpolate untrusted data as format patterns.
- Lock down and integrity-protect your logging configuration files so an attacker cannot repoint an appender (the CVE-2021-44832 vector).
- Hunt for shaded/relocated copies. A dependency scanner that reads inside JARs — not just declared coordinates — is essential, because relocated Log4j classes will not show up under the normal package name.
How to monitor Log4j with SCA and reachability
Log4Shell proved that the hard part of remediation is not applying the patch — it is knowing where the vulnerable library actually is, including inside third-party and shaded artifacts. A continuously maintained software bill of materials is the difference between reacting in minutes and spending weeks grepping build outputs.
Safeguard's software composition analysis resolves your full Java dependency graph, detects Log4j even when it is transitive or relocated inside a fat JAR, and adds reachability so you can tell a genuinely exposed logging path from a dormant copy. When a patched release exists, autonomous auto-fix opens a tested pull request that bumps Log4j to a safe version. Teams standardizing incident response across a fleet of Java services can see how it scales on the pricing overview, and developers verify fixes locally and in CI with the Safeguard CLI.
Bring continuous, prioritized dependency analysis to your Java services — get started free or read the documentation.
Frequently Asked Questions
Which Log4j version is safe in 2026?
Run Log4j 2 at 2.17.1 or later; a current 2.x release is best. 2.17.1 is the version that fixes all four Log4Shell-era CVEs — the original RCE (CVE-2021-44228), the incomplete-fix RCE/DoS (CVE-2021-45046), the recursion DoS (CVE-2021-45105), and the JDBC-appender RCE (CVE-2021-44832). Anything earlier is missing at least one fix.
Is Log4j 1.x safe if I am careful?
No. Log4j 1.x has been end-of-life since 2015 and ships unfixable deserialization and SQL-injection flaws such as CVE-2019-17571 and CVE-2022-23305. There is no patched 1.x release; the only remediation is migrating to Log4j 2 or another maintained logging backend.
Am I still exposed to Log4Shell if I patched to 2.15.0?
Partially. 2.15.0 only addressed the original CVE-2021-44228, and it was found to be incomplete. You need at least 2.16.0 for the follow-on RCE/DoS, 2.17.0 for the recursion DoS, and 2.17.1 for the JDBC-appender RCE. Standardize on 2.17.1 or later.
Why was Log4Shell so hard to fully remediate?
Because Log4j is buried transitively inside countless frameworks and vendor products, often shaded or relocated so it does not appear under its normal package name. Many teams could not answer "where is Log4j?" quickly, which is why maintaining an accurate SBOM and scanning inside artifacts matters so much.
How do I find every copy of Log4j in my environment?
Use SCA that resolves the full transitive graph and inspects inside packaged artifacts, then maintain a continuous SBOM. That lets you locate declared, transitive, and shaded copies alike, and reachability analysis then tells you which of those copies sit on a code path that actually logs untrusted input.