Internet security research and reporting
Analysis Updated Retrospective · 2021 CVE-2021-44228CVE-2021-45046

Log4Shell: the dependency inventory that patching could not replace

A retrospective on embedded Java dependencies, incomplete early fixes and the evidence needed to close a remediation ticket.

Attacker-controlled text; Logging input; Log4j Core lookup; External naming endpoint. Original diagram of the incident mechanism and review boundaries.
FISRO schematic: Attacker-controlled text; Logging input; Log4j Core lookup; External naming endpoint. FISRO

Summary

Log4Shell, CVE-2021-44228, exposed a JNDI lookup flaw in Log4j Core in December 2021. Subsequent fixes and exploitation reports made package discovery only the first step. This analysis separates build inventory, deployed artefacts and running services to explain what a defensible remediation record needs.

The incident was a dependency problem before it was a patching problem

The December 2021 Log4Shell disclosures forced organisations to answer a deceptively difficult question: where does our software actually log untrusted text? A Java application could include the vulnerable logging implementation several dependency layers below its own code. The team responsible for a public service might not own that dependency or even know it was present.

Apache identifies CVE-2021-44228 as a JNDI lookup problem in log4j-core. Attacker-controlled log messages or parameters could cause interaction with an attacker-controlled endpoint and, under the relevant conditions, arbitrary code execution. The distinction between log4j-core and log4j-api matters: finding the API alone does not establish exposure to this vulnerability.

Microsoft subsequently documented exploitation across several kinds of activity, including access brokers and botnets. Its observations are evidence of real exploitation, rather than proof that every organisation receiving a suspicious request was compromised. That difference should survive every incident summary.

Three inventories that answer different questions

An installed-package list, a build dependency graph and the contents of a running workload describe different states. Treating one as a substitute for the others leaves an obvious recovery gap.

Inventory Useful evidence What it cannot establish alone
Build dependencies Which component and version a release intended to include What was actually deployed or loaded
Deployed artefacts JARs, container digests, appliance releases Whether an older process is still running
Runtime state Process age, loaded application release, deployment identity Whether a dormant image will return during scaling

The operational task is to join these records using a service owner and an immutable release identity. A scanner finding without an owner becomes a ticket queue; an owner without an artefact identity cannot prove that remediation reached production.

Why the first fix was not the final answer

Apache's security record documents an incomplete fix in 2.15.0 under certain non-default configurations, tracked separately as CVE-2021-45046. That makes historical advice to install the first emergency release a poor permanent baseline. Present-day remediation should follow the current maintainer or appliance-vendor guidance for the supported product line.

For an administrator, the useful question is not simply whether a machine has a version above an old headline number. It is whether the supported application release includes the relevant fixes, whether its vendor backported them, and whether the process now running was started from that release. For a closed appliance, the vendor's affected-product statement is more useful than assumptions about an internal JAR filename.

A closure test for legacy Java services

Start with deployed services and their suppliers. Ask each owner for the running application version, its dependency evidence and the vendor's security statement. Keep the collection read-only: examining an artefact or dependency report is preferable to sending lookup payloads to production.

Then examine the route back into service. A patched current container is insufficient if a deployment rollback, a scheduled batch job or an autoscaling template can restore an older image. Include disaster-recovery images and rarely used administrative services in the same reconciliation.

Finally, record the exposure window separately from remediation. An update closes a vulnerable execution path; it does not explain what happened before that update. Preserve relevant logs and investigate suspicious process execution or outbound activity according to the incident's scope. Do not describe every DNS callback as confirmed remote code execution.

The parallel with the xz incident

The xz backdoor concerned deliberately altered release material rather than an accidental logging flaw. Both incidents expose a limit of dependency names: a component's presence is the beginning of an investigation, not the conclusion. xz required attention to the source artefact and build conditions; Log4Shell required attention to the implementation, configuration and reachable input.

FISRO's assessment is that a useful software inventory should support four linked questions: what code, from which artefact, running where, with which untrusted inputs? A list of package names answers only part of that chain.

Read the historical fix boundaries by Java line

Apache's advisory separates the Java compatibility lines. For the original CVE-2021-44228, it records fixed releases 2.3.1 for Java 6, 2.12.2 for Java 7 and 2.15.0 for Java 8 or later. Its CVE-2021-45046 entry explains why the initial 2.15.0 correction was incomplete in certain non-default configurations. Subsequent December advisories addressed further issues. Those distinctions are lost in a single statement that Log4j was patched.

Historical issue Relevant implementation Original fix boundaries recorded by Apache
CVE-2021-44228 log4j-core, with attacker-controlled lookup input 2.3.1, 2.12.2, 2.15.0, according to Java compatibility line
CVE-2021-45046 Certain non-default Thread Context Lookup configurations 2.3.1, 2.12.3, 2.16.0
Current maintenance decision The supported application and Java environment Follow current vendor guidance, including later advisories and backports

The table describes response history. It is not a recommendation to choose an obsolete release solely because it crossed one historical boundary. Keep the CVE, configuration and compatibility line attached to each decision.

Locate embedded JARs without triggering a lookup

In an authorised local artefact directory, an initial inventory can list Java archives:

rg --files --no-ignore -g '*.jar' -g '*.war' -g '*.ear' .
unzip -l application.jar | rg 'log4j-(core|api)|BOOT-INF/lib|WEB-INF/lib'

The second command inspects an example archive; replace its name with the collected build artefact. It does not launch the application or send a lookup string. Nested archives, shaded components and renamed libraries require deeper build evidence. An empty filename search cannot establish that the implementation is absent.

Preserve the artefact digest and its deployment identity. Match the result to the dependency report produced by the trusted build. If the server is an appliance, obtain the supplier's product-specific statement; a guessed internal library version is weaker evidence than a supported build assessment.

Two parser cases that sharpen the comparison

In September 2023, libwebp's CVE-2023-4863 required attention beyond a browser update because image decoding also occurred in bundled components and processing workers. The operational similarity is hidden component ownership. The trigger differs: decoding image data rather than interpreting a logging lookup.

In October 2026, Brotli's CVE-2026-111497 raised a related native-decoder inventory problem across runtime and application packaging. The fix has to reach the deployed decoder, including embedded copies. An operating-system library update and a rebuilt runtime can be separate delivery events.

For Log4Shell, preserve the equally specific closure condition: the relevant logging implementation and configuration were assessed in the deployed application, the supported correction reached the running service, and old images or recovery templates cannot silently restore the affected build. Any earlier suspicious activity remains a separate incident question.

What to do

Inventory deployed JAR/WAR/EAR artefacts and distinguish log4j-core from log4j-api. Match the full vendor-supported release to the Java line and relevant advisories, then verify the running service and old recovery images.

What remains unverified

This review does not establish the current security of a particular Java service or appliance. Historical exploitation reports do not show whether any specific reader's systems were compromised.

Timeline

  1. Public disclosure of the Log4j vulnerability, as recorded by Microsoft's response summary. [Microsoft Security Response Center]

Methodology

AI-assisted research and drafting. The article synthesises the linked primary documents; technical examples are read-only checks or proposed exercises, not claimed FISRO reproductions. Dates and product conditions are attributed to their sources. Editorial interpretation and diagrams are identified as FISRO analysis.

Sources

Primary sources are maintainers, vendors, official bodies and original documents. Secondary sources are reporting by others.

  1. Apache Logging Services security advisories Apache Software Foundation Primary Accessed 30 Oct 2026 CVE-2021-44228 and CVE-2021-45046 sections; implementation boundary and incomplete initial fix.
  2. Guidance for preventing, detecting, and hunting for Log4j 2 exploitation Microsoft Threat Intelligence Primary Published 11 Dec 2021 Accessed 30 Oct 2026 Original observations of exploitation; do not treat scanning as proof of compromise.
  3. Microsoft's Response to CVE-2021-44228 Apache Log4j 2 Microsoft Security Response Center Primary Accessed 30 Oct 2026 Records disclosure on 9 December 2021 and affected-product response.

Updates and corrections

  • Update · 30 October 2026, 01:39 UTC
    Expanded technical conditions, read-only diagnostics, incident comparisons and original diagrams; AI-assisted drafting disclosed. Original publication date retained.

Found an error? Request a correction. We record every substantive change on this page, as set out in our corrections policy.

Related coverage