BackendBench
Coffee
Doctor

Maven POM doctor

Paste your pom.xml. The doctor compares dependencies against a built-in table of known vulnerable or end-of-life versions, and checks the build for SNAPSHOTs, duplicates, version ranges, insecure repositories and unpinned plugins. No network calls are made.

Everything runs in your browser. Nothing you paste is uploaded. Also try the paste-anything box or the AI-output verifier.

What the POM doctor checks

Most supply-chain incidents in Java arrive through an old transitive version nobody looked at: Log4Shell, Spring4Shell and Text4Shell all shipped in ordinary pom.xml files. A static table cannot replace a scanner such as OWASP Dependency-Check or Dependabot, but it catches the famous cases instantly and offline, and the structural rules find the build hygiene problems that make a release irreproducible.

There are 36 rules in this doctor: 13 high severity, 14 medium and 9 low. Each rule has a stable anchor, so you can link a teammate straight to the explanation, for example /doctor/pom/#rule-old-log4j-core.

All 36 rules

Highorg.apache.logging.log4j:log4j-core/api is old or vulnerable#

Why it matters. log4j-core before 2.17.1 is affected by Log4Shell (CVE-2021-44228) and follow-up remote code execution bugs.

Fix. Upgrade to the latest 2.x release (2.17.1 is the minimum). Maven to Gradle converter

<project><dependencies><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>0.1</version></dependency></dependencies></project>

Highlog4j:log4j is old or vulnerable#

Why it matters. Log4j 1.x is end of life since 2015 and has unfixable vulnerabilities (JMSAppender, SocketServer).

Fix. Move to log4j2 or Logback; the log4j-1.2-api bridge keeps old calls working. Maven to Gradle converter

<project><dependencies><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>0.1</version></dependency></dependencies></project>

Highcom.fasterxml.jackson.core:jackson-databind is old or vulnerable#

Why it matters. Older jackson-databind releases have deserialization gadget CVEs, including several rated critical.

Fix. Upgrade to a current 2.17+ release, and let the Spring Boot BOM manage all Jackson modules together. Maven to Gradle converter

<project><dependencies><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>0.1</version></dependency></dependencies></project>

Mediumorg.springframework:spring-core/beans/context/web/webmvc is old or vulnerable#

Why it matters. Spring Framework 5.2 and older are out of open-source support; Spring4Shell (CVE-2022-22965) affects 5.3.0 to 5.3.17.

Fix. Upgrade to Spring Framework 6.1+ / Spring Boot 3.x, or at least the latest 5.3.x. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>0.1</version></dependency></dependencies></project>

Highorg.springframework:spring-core/beans/context/web/webmvc is old or vulnerable#

Why it matters. Spring Framework before 5.3.18 is vulnerable to Spring4Shell remote code execution on JDK 9+ with WAR deployment.

Fix. Upgrade to 5.3.18 or newer, preferably Spring Framework 6. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>0.1</version></dependency></dependencies></project>

Highorg.apache.struts:struts2-core is old or vulnerable#

Why it matters. Struts 2 has a long history of remote code execution flaws (Equifax breach).

Fix. Move to Spring MVC, or the latest Struts 6.x with all security releases. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.apache.struts</groupId><artifactId>struts2-core</artifactId><version>0.1</version></dependency></dependencies></project>

Highcommons-collections:commons-collections is old or vulnerable#

Why it matters. commons-collections before 3.2.2 enables a deserialization gadget chain.

Fix. Use commons-collections4 or upgrade to 3.2.2. Maven to Gradle converter

<project><dependencies><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>0.1</version></dependency></dependencies></project>

Highcom.alibaba:fastjson is old or vulnerable#

Why it matters. fastjson before 1.2.83 has a series of autotype remote code execution bypasses.

Fix. Upgrade to 1.2.83+, or move to fastjson2 or Jackson. Maven to Gradle converter

<project><dependencies><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>0.1</version></dependency></dependencies></project>

Highorg.yaml:snakeyaml is old or vulnerable#

Why it matters. SnakeYAML before 2.0 can instantiate arbitrary classes from YAML (CVE-2022-1471).

Fix. Upgrade to 2.x; Spring Boot 3.x already does. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>0.1</version></dependency></dependencies></project>

Mediumcom.google.code.gson:gson is old or vulnerable#

Why it matters. Gson before 2.8.9 can be made to deserialize into unexpected types and crash (CVE-2022-25647).

Fix. Upgrade to 2.10 or later. Maven to Gradle converter

<project><dependencies><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>0.1</version></dependency></dependencies></project>

Highorg.apache.commons:commons-text is old or vulnerable#

Why it matters. commons-text 1.5 to 1.9 interpolation allows remote code execution (Text4Shell, CVE-2022-42889).

Fix. Upgrade to 1.10.0 or later. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.apache.commons</groupId><artifactId>commons-text</artifactId><version>0.1</version></dependency></dependencies></project>

Mediumcom.h2database:h2 is old or vulnerable#

Why it matters. H2 before 2.2.220 has remote code execution through the console and JDBC URL abuse.

Fix. Upgrade, and never expose the console. Maven to Gradle converter

<project><dependencies><dependency><groupId>com.h2database</groupId><artifactId>h2</artifactId><version>0.1</version></dependency></dependencies></project>

Mediumorg.apache.tomcat.embed:tomcat-embed-core is old or vulnerable#

Why it matters. Old embedded Tomcat releases carry request smuggling and DoS CVEs (HTTP/2 rapid reset, partial PUT RCE).

Fix. Upgrade Spring Boot, or override tomcat.version to the latest patch. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>0.1</version></dependency></dependencies></project>

Mediumorg.apache.httpcomponents:httpclient is old or vulnerable#

Why it matters. HttpClient before 4.5.13 mishandles URI parsing (CVE-2020-13956).

Fix. Upgrade to 4.5.14 or move to httpclient5. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>0.1</version></dependency></dependencies></project>

Lowmysql:mysql-connector-java is old or vulnerable#

Why it matters. The coordinates mysql:mysql-connector-java were retired; fixes only land in com.mysql:mysql-connector-j.

Fix. Switch to com.mysql:mysql-connector-j. Maven to Gradle converter

<project><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>0.1</version></dependency></dependencies></project>

Lowjunit:junit is old or vulnerable#

Why it matters. JUnit 4 is in maintenance mode and lacks modern features such as parameterised nested tests.

Fix. Move to JUnit 5 (junit-jupiter), keeping vintage-engine for old tests. Maven to Gradle converter

<project><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>0.1</version></dependency></dependencies></project>

Mediumjavax.servlet:javax.servlet-api is old or vulnerable#

Why it matters. The javax.* servlet API does not work with Spring Boot 3 / Tomcat 10, which use jakarta.servlet.

Fix. Use jakarta.servlet:jakarta.servlet-api (provided scope). Maven to Gradle converter

<project><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>0.1</version></dependency></dependencies></project>

Mediumorg.hibernate:hibernate-core is old or vulnerable#

Why it matters. Hibernate 5.4 and older are out of support and miss SQL injection fixes in 5.6.x.

Fix. Upgrade to 5.6.15+ or Hibernate 6 with Spring Boot 3. Maven to Gradle converter

<project><dependencies><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-core</artifactId><version>0.1</version></dependency></dependencies></project>

HighSNAPSHOT dependency in a release build#

Why it matters. A SNAPSHOT changes without a version bump, so the same release tag builds different artifacts and the Maven release plugin refuses.

Fix. Depend on a released version before tagging. Maven to Gradle

<project><version>1.0.0</version><dependencies><dependency><groupId>a</groupId><artifactId>b</artifactId><version>2.0-SNAPSHOT</version></dependency></dependencies></project>

MediumSNAPSHOT parent#

Why it matters. The parent POM can change under you between builds.

Fix. Pin the parent to a released version.

<project><parent><groupId>a</groupId><artifactId>p</artifactId><version>1.0-SNAPSHOT</version></parent></project>

MediumDependency declared twice#

Why it matters. Maven warns and the later declaration wins, so the version you read is not always the one used.

Fix. Keep one declaration; move shared versions into dependencyManagement or a property.

<project><dependencies><dependency><groupId>a</groupId><artifactId>b</artifactId><version>1</version></dependency><dependency><groupId>a</groupId><artifactId>b</artifactId><version>2</version></dependency></dependencies></project>

HighVersion range or LATEST/RELEASE#

Why it matters. Open ranges make the build non-reproducible; LATEST and RELEASE were removed from Maven 3 resolution and a surprise upgrade can break production.

Fix. Pin an exact version and update it deliberately (Dependabot or Renovate).

<project><dependencies><dependency><groupId>a</groupId><artifactId>b</artifactId><version>[1.0,)</version></dependency></dependencies></project>

LowVersion overridden where Spring Boot already manages it#

Why it matters. Hard-coding a version for a Boot-managed artifact such as jackson, slf4j or hibernate can pull it out of step with the rest of the stack.

Fix. Remove the version and let spring-boot-starter-parent decide, or override the version property.

<project><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.0</version></parent><dependencies><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.0</version></dependency></dependencies></project>

LowSame group at several hard-coded versions#

Why it matters. When one library family (Jackson, Netty, AWS SDK) is declared with different versions the runtime mixes them and fails with NoSuchMethodError.

Fix. Import the vendor BOM in dependencyManagement and drop the per-artifact versions.

<project><dependencies><dependency><groupId>io.netty</groupId><artifactId>netty-handler</artifactId><version>4.1.100</version></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-codec</artifactId><version>4.1.90</version></dependency></dependencies></project>

MediumDependency with no version and no management#

Why it matters. Maven fails with "dependencies.dependency.version is missing" unless a parent or BOM supplies it.

Fix. Add a version or import a BOM.

<project><dependencies><dependency><groupId>a</groupId><artifactId>b</artifactId></dependency></dependencies></project>

HighRepository over plain http#

Why it matters. Artifacts downloaded over http can be swapped by anyone on the path; Maven 3.8.1+ blocks http repositories entirely.

Fix. Use https URLs.

<project><repositories><repository><id>r</id><url>http://repo.example.com/maven</url></repository></repositories></project>

Mediumsystem scope dependency#

Why it matters. systemPath jars are not resolved from a repository, are deprecated and break in other build environments and in the shade/boot plugins.

Fix. Install the jar into your repository manager, or use a file repository.

<project><dependencies><dependency><groupId>a</groupId><artifactId>b</artifactId><version>1</version><scope>system</scope><systemPath>/x.jar</systemPath></dependency></dependencies></project>

MediumPlugin without a version#

Why it matters. Maven uses whatever version its super-POM binds, which differs per Maven release and makes builds irreproducible (and warns).

Fix. Pin plugin versions in pluginManagement.

<project><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId></plugin></plugins></build></project>

Mediummaven-surefire-plugin older than 2.22#

Why it matters. Surefire before 2.22 cannot run JUnit 5 tests; they are silently skipped and the build is green with zero tests.

Fix. Use maven-surefire-plugin 3.x.

<project><build><plugins><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.12.4</version></plugin></plugins></build></project>

Lowmaven-compiler-plugin older than 3.8#

Why it matters. Versions before 3.6 do not understand <release> and Java 9+ modules.

Fix. Use 3.11 or newer and <maven.compiler.release>.

<project><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.1</version></plugin></plugins></build></project>

LowNo Java version declared#

Why it matters. Without maven.compiler.release (or java.version) the compiler default depends on the Maven and JDK version, so CI and laptops compile differently.

Fix. Set <maven.compiler.release>21</maven.compiler.release>. Java versions

<project><modelVersion>4.0.0</modelVersion></project>

Lowproject.build.sourceEncoding not set#

Why it matters. The platform default encoding is used, so a file with รฉ compiles differently on Windows and Linux (and Maven warns).

Fix. Add <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>.

<project><modelVersion>4.0.0</modelVersion><properties><x>1</x></properties></project>

MediumSpring Boot parent is out of support#

Why it matters. Spring Boot 2.x reached end of open-source support (2.7 in November 2023), and 3.0 to 3.3 are also past their window.

Fix. Upgrade to a supported Boot 3.x line; use OpenRewrite recipes for the javax to jakarta move. Spring env converter

<project><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version></parent></project>

LowLombok on the runtime classpath#

Why it matters. Lombok is a compile-time annotation processor; shipping it adds a pointless jar.

Fix. Use <scope>provided</scope> (or optional).

<project><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency></dependencies></project>

LowTest library without test scope#

Why it matters. JUnit, Mockito and AssertJ in compile scope end up in the production jar or war.

Fix. Add <scope>test</scope>.

<project><dependencies><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>5.0.0</version></dependency></dependencies></project>

HighThis is not a well-formed pom.xml#

Why it matters. Maven stops with "Non-parseable POM" when tags are unbalanced.

Fix. Close every tag; paste into the XML formatter to find the broken spot. XML formatter

<project><dependencies></project>

Frequently asked questions

How does it know a version is vulnerable without the internet?

It uses a small static table of widely known problem versions, for example log4j-core before 2.17.1 or snakeyaml before 2.0. It is a quick first check, not a full vulnerability database.

Does it resolve properties and parent versions?

Properties declared in the same file, such as ${jackson.version}, are resolved. Versions inherited from a parent or BOM that is not pasted cannot be seen, so dependencies without a version are skipped when a parent is present.

What counts as a SNAPSHOT problem?

A SNAPSHOT dependency inside a project whose own version is a release. The build is not reproducible because the SNAPSHOT can change without a version bump.

Should I upgrade everything it lists?

Prioritise the high severity rows, which are exploitable flaws. Medium and low rows are hygiene and support-window warnings you can schedule.

More tools you might need