Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

What Log4Shell taught us about open-source supply-chain security

On 9 December 2021, a security researcher publicly disclosed a critical remote code execution vulnerability in Apache Log4j 2, a Java logging library used by hundreds of millions of systems worldwide. Within hours, proof

On 9 December 2021, a security researcher publicly disclosed a critical remote code execution vulnerability in Apache Log4j 2, a Java logging library used by hundreds of millions of systems worldwide. Within hours, proof-of-concept exploits were circulating. Within days, CISA, the NSA, the FBI and security teams around the world were in full emergency response mode.

CVE-2021-44228, quickly nicknamed Log4Shell, became the defining supply-chain security incident of the decade. Four years later it's worth examining what it actually revealed about how software is built and consumed — because most of the underlying vulnerabilities in process and practice are still present.

Why it was so bad

Log4j is a transitive dependency. Most of the systems it ran on didn't import it directly. It was imported by the logging framework used by the web framework used by the application framework used by the actual product. Three, four, five levels deep in a dependency tree, in software that had been running unchanged for years.

That's why the question "do we use Log4j?" was so hard to answer. Developers who had never heard of Log4j were running it. When you ask a developer what their application depends on, they'll tell you the 20 packages in their pom.xml. They often can't tell you what those 20 packages depend on. The actual dependency tree of a medium-sized Java application routinely has 400–800 components.

The lesson: you cannot know your exposure to a vulnerability if you don't have a complete, machine-readable inventory of your dependencies — including transitives.

The tools weren't ready

Many organizations discovered during Log4Shell that their vulnerability scanning tools were either:

  • Not covering transitives — only checking direct dependencies against the CVE database.
  • Slow to update — commercial scanners that relied on vendor-maintained databases (rather than the OSV mirror) took days to get signatures for Log4Shell variants (there were four CVEs in two weeks).
  • Not deployed — teams had scanners available in theory but not integrated into CI/CD, so the check was manual and ad hoc.

The open-source OSV project, which Log4Shell helped drive adoption of, operates a different model: advisories are submitted by security researchers and ecosystem owners, the database is open and machine-readable, and it covers transitives by design.

Why the patch cycle was so painful

After Log4j 2.15.0 was released to fix the initial CVE, it was found to have a partial bypass (CVE-2021-45046), requiring 2.16.0. Then a DoS vulnerability was found (CVE-2021-45105), requiring 2.17.0. Then a separate RCE in the 1.x branch was found (CVE-2019-17571, which had been known but deprioritised) and a new one (CVE-2022-23302). Organizations that thought they were done patching kept getting pulled back.

The lesson here is that knowing the version you're running is not enough — you need to know the exact CVE history for each component you ship, and you need to be able to update that knowledge quickly when new advisories are published.

What actually protects you

Log4Shell accelerated adoption of several practices that were already best-in-class:

Automated dependency scanning in CI. If scanning runs on every PR, Log4Shell-class vulnerabilities are caught when they enter your dependency tree, not six months later during a security audit. The scan should cover the full transitive tree, not just direct dependencies.

SBOM generation in every build. An SBOM that's generated and stored at build time means that when a vulnerability drops, you can query "which builds contain this PURL?" rather than re-scanning every repo.

Dependency pinning in lockfiles. Lockfiles (package-lock.json, poetry.lock, Cargo.lock) record exact resolved versions, so you know precisely which version of which transitive you're shipping — not a range.

Exploitability-first prioritisation. When you have 400 vulnerable packages, you can't fix them all in a week. Log4Shell was a CVSS 10 with EPSS near 1.0 and almost immediately KEV-listed — the highest possible signal. Organizations that had already built exploitability-based triage were able to correctly identify it as the only thing that mattered that week.

VEX documents for your customers. Vendors who could quickly produce a Vulnerability Exploitability eXchange (VEX) document saying "we use Log4j but in a configuration where JNDI lookup is disabled and we are not vulnerable" saved enormous amounts of time on both sides of supplier relationships.

The supply-chain attack surface didn't shrink after Log4Shell. The xz-utils backdoor in 2024 — a deliberately inserted backdoor in a widely-used compression library — showed that the problem extends beyond accidental vulnerabilities to deliberate supply-chain compromise. The practices Log4Shell accelerated remain the best defence.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.