Every copy of log4j-core in your build must be found. Not just the one you declared. Transitive pulls, shaded JARs, WARs, EARs, nested ZIPs. The vulnerable code lives inside log4j-core alone. log4j-api does not carry the JNDI lookup class. Collect every instance, then check each version.
Use Maven to List Log4j Dependencies
Run the Dependency Tree
Open a terminal in the root and run:
mvn dependency:tree -Dincludes=org.apache.logging.log4jThe output is a tree of every Log4j artifact, direct and transitive. Look for log4j-core entries. Each one prints its version. Multiple entries mean the same library arrived through different paths, or you have several versions. Write them all down.
To narrow the results, adjust the filter to log4j-core only. This works on any Maven build.
Find Log4j in Gradle Projects
Pinpoint with dependencyInsight
Run this in the project directory:
gradle dependencyInsight --dependency log4j-coreThe task reports every location where the library appears and the path that pulled it in. It also shows the version. If nothing matches, the task tells you. Use it to confirm no hidden copies linger.
You can also dump the full tree with gradle dependencies and grep for log4j, but dependencyInsight is faster and spares you unrelated output.
Inspect Shaded and Fat JARs
Check for the JndiLookup Class
Log4j can be bundled inside fat, uber, or shaded JARs, and inside WAR and EAR files. Searching filenames like log4j-core-*.jar misses these copies. Look for the class that signals the vulnerable code is present.
JAR files are ZIP archives. List them with unzip:
The string org/apache/logging/log4j/core/lookup/JndiLookup.class means Log4j 2 core is inside. WAR and EAR files work the same way. Repeat this for every archive in your deployment.
If you find the class, extract the archive and locate the log4j-core.jar within. Read META-INF/MANIFEST.MF to get the version.
Why This Matters
Maven's Shade plugin and Gradle's Shadow plugin bundle dependencies into a single JAR. The bundled log4j-core never appears as a separate file. Scanning for JndiLookup catches it.
Search Across All Archives in Your Project
- List every archive:
find . -name '*.jar' -o -name '*.war' -o -name '*.ear' -o -name '*.zip' - For each one, run
unzip -land grep for JndiLookup or log4j-core. - When you get a match, note the archive path. Extract the version from the manifest or from a log4j2.properties file if one is present.
- Record every version. Even duplicates.
This step catches shaded copies that legacy deployments and vendor libraries often bury.
Use a Software Bill of Materials (SBOM)
An SBOM records every component and its version in a machine-readable format like CycloneDX or SPDX. If your project already generates one, query it for log4j-core entries instead of scanning archives by hand.
Generate an SBOM from Maven with the CycloneDX plugin. Gradle has a comparable plugin. The output lists each dependency, its version, and whether it is direct or transitive. Search the file for log4j-core and note the version fields.
If you do not have an SBOM yet, generating one builds a single source of truth for all future dependency checks.
Distinguish Log4j-core from Log4j-api
Many projects pull in both artifacts. Only log4j-core contains the vulnerable JNDI lookup code. If your inventory shows log4j-api alone, the relevant vulnerability does not affect you.
When you review a dependency tree, check the artifact name. The Maven and Gradle commands both print it. Stop if you see only log4j-api. If you see log4j-core, check its version.
A library may depend on log4j-core transitively. Even when your project declares only log4j-api, a transitive pull can bring the core library in. The tree commands surface this.
Check Each Version Against a Database
You have collected every log4j-core version. Now determine which ones are vulnerable. Enter each version into the site's checker. It reports whether that version is affected by the relevant vulnerability or other Log4j vulnerabilities.
Record the results per copy. Treat multiple versions independently. A patched version in one location does not protect an unpatched copy inside a shaded JAR elsewhere. Replace or upgrade every vulnerable instance.