Incidents & Vulnerabilities

Log4Shell (CVE-2021-44228) — a logging library flaw, and why teams couldn't quickly tell if they used it

Log4Shell was a CVSS 10.0 RCE in Log4j in December 2021 that hit teams through transitive dependencies. How logging became an attack path, and the lessons.

Published 2026-06-07 Updated 2026-10-23 4 min read
On this page

Revisiting a major past incident, not to reproduce the attack, but for the lessons that still apply to your operations.

2021/12
disclosed
10.0
CVSS (worst class)
transitive
the core problem
several
follow-up CVEs

What happened: writing a log line became an attack path

Log4j handled the mundane task of writing logs, and was used very widely in Java applications. The flaw: the library interpreted a certain pattern inside logged strings as something to "resolve by reaching out externally," and ended up executing externally specified code.

So an attacker who got a crafted string into "somewhere that gets logged" (a username, a header) could reach code execution. That a passive act like logging could become an attack path came as a major surprise.

Why it was hard to tell whether you were affected

Most apps never installed Log4j directly. A framework or SDK pulled it in. This is a transitive dependency: a dependency of a dependency of a dependency. Without your "bill of materials," you couldn't even tell if you were affected.

Your app (one line in package.json)
└─▶
framework / SDK (direct dependency)
└─▶
a logging component (dependency of a dependency)
└─▶
Log4j ← the vulnerability (never installed directly)
You added one line, but dozens of 'dependencies of dependencies' sit beneath it. Log4j was among them.

The biggest problem was not knowing whether you used it

When you "can't tell if you use it," you can't even prioritize the response. Whether you held a bill of materials (SBOM) largely decided how fast you could respond.

Timeline

  1. 2021-12-09–10

    The flaw becomes widely known; the world scrambles to check "are we affected?"
  2. right after

    Emergency patching and stopgap mitigations roll out; exploit attempts spike.
  3. afterward

    Several follow-up CVEs (fixes to the fix) are published — "fixed once" wasn't the end.

Lessons that still apply

1

Have an SBOM (bill of materials)

Make visible what your app uses internally: npm ls, lockfiles and SBOM tools show what's actually running. Looking only at "what you installed directly" isn't enough.

2

Machine-monitor dependencies

The moment a CVE drops, know automatically if it applies (Dependabot / osv-scanner), including transitive dependencies. Manual checks always miss something.

3

Make patching fast

Practice "upgrade, verify, ship" routinely so you can do it quickly in an emergency. See building dependency monitoring.

4

Follow the follow-up CVEs

After Log4Shell, fixes to the fix appeared. Don't stop at "fixed once"; track the follow-ups.

Sources and scope

These primary references support the settings, scope or remediation discussed above; links were checked on October 23, 2026. Consult their version and configuration conditions. Checklist priorities and lessons are this site's guidance, not a full-article revalidation or a safety guarantee.

FAQ

QWhat was new about the Log4Shell problem?
A

It exposed the danger of transitive dependencies at global scale: being vulnerable through a library used inside another library, even with no direct install. Without knowing your SBOM, you couldn't even tell if you were affected.

QWhy did logging become an attack vector?
A

Log4j interpreted certain text inside logged strings as something to 'resolve by reaching out externally'. An attacker only had to get a crafted string somewhere that gets logged (a username, an HTTP header), turning a passive logging path into code execution.

QHow do I avoid repeating it?
A

Three things: machine-monitor dependencies (Dependabot/osv-scanner), generate an SBOM to see what you actually use, and run an update process fast enough to patch quickly. Also follow the follow-up CVEs (fixes to the fix).