Safeguard
Security

CVE-2020-25638: SQL Injection in Hibernate ORM Explained

CVE-2020-25638 is a SQL injection flaw in hibernate-core that surfaces when SQL comments are enabled and literals are used in JPA Criteria queries. Here is who is affected and how to remediate it.

Marcus Chen
DevSecOps Engineer
5 min read

CVE-2020-25638 is a SQL injection vulnerability in Hibernate ORM's hibernate-core, where unsanitized literal values can be embedded into SQL comments when the hibernate.use_sql_comments setting is enabled. It affects hibernate-core versions before 5.3.20.Final and the 5.4.x line up to and including 5.4.23.Final. Because Hibernate is the default JPA provider in a huge swath of Java applications, this one shows up frequently in dependency scans even though the exploit conditions are specific.

What the vulnerability does

Hibernate has a configuration option, hibernate.use_sql_comments, that annotates generated SQL with comments to aid debugging. When it is turned on, Hibernate embeds context, including query literals, into the comment portion of the generated SQL statement.

The flaw is that in the affected versions, literals used in JPA Criteria API queries were placed into those SQL comments without proper sanitization. A literal containing comment-terminating or SQL control sequences could break out of the comment boundary and inject arbitrary SQL into the executed statement. In other words, a debugging convenience became an injection point.

The root cause was in the prependComment handling within Dialect.java, and the injection points were the various toStatementString methods across the SQL statement builders (select, update, delete, and so on). The fix adds comment escaping via a Dialect.escapeComment() call at each of those locations, so a literal can no longer terminate the comment early.

The two conditions that must both hold

CVE-2020-25638 is only exploitable when both of these are true:

  1. hibernate.use_sql_comments is set to true. It is false by default, so applications that never enabled it are not exposed through this path.
  2. The application uses literal values (rather than bound parameters) in JPA Criteria API queries, and those literals can carry attacker-controlled content.

That combination is narrower than a blanket "Hibernate is vulnerable" reading suggests. If you left SQL comments off, which is the default, your practical exposure to this specific CVE is limited. Confirm the setting before you treat it as a fire drill, but do not use "it is probably off" as a reason to skip the patch, since configuration drifts and a future change could flip it on.

Affected and fixed versions

  • Versions before 5.3.20.Final are affected; upgrade to 5.3.20.Final on the 5.3 line.
  • Versions 5.4.0.Final through 5.4.23.Final are affected; upgrade to 5.4.24.Final on the 5.4 line.

The impact, per the advisory, is to data confidentiality and integrity: a successful injection could read unauthorized data or manipulate it, and potentially enable further attacks depending on the database permissions Hibernate runs with.

Checking whether you are affected

Hibernate is frequently transitive, arriving through Spring Data JPA, application-server BOMs, or other frameworks. Print the resolved version.

Maven:

mvn dependency:tree -Dincludes=org.hibernate:hibernate-core

Gradle:

./gradlew dependencies --configuration runtimeClasspath | grep hibernate-core

Then check the setting. Look in persistence.xml, application.properties, or application.yml:

# If this is true and you use Criteria literals, you are exposed
hibernate.use_sql_comments=true

Remediating CVE-2020-25638

The durable fix is the version upgrade. Pin the patched version, preferring Maven's dependencyManagement or Gradle constraints if hibernate-core is transitive:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.4.24.Final</version>
    </dependency>
  </dependencies>
</dependencyManagement>

If you are on Spring Boot, prefer bumping the Spring Boot BOM to a version that already manages a patched hibernate-core, rather than pinning Hibernate independently and risking a mismatch with the rest of the managed stack.

As an immediate stopgap while a patch is scheduled, you can disable hibernate.use_sql_comments (or confirm it is already off), which removes the exploit precondition. Treat that as mitigation, not a fix: the vulnerable code is still present, and the setting could be re-enabled by a later change. Patch as soon as the release window allows.

The broader habit: parameterize everything

CVE-2020-25638 is a reminder that even a mature, widely trusted ORM can mishandle literals. The defensive habit that would have blunted it, and blunts SQL injection generally, is to use bound parameters instead of inlined literals in every query, Criteria API included. Parameterized queries send the value to the database separately from the SQL text, so it can never be interpreted as SQL structure.

Finding the vulnerable Hibernate version in a deep dependency tree is where automation earns its place. A software composition analysis scan resolves the full graph and flags an affected hibernate-core even when it is pulled in transitively by a framework, and a CI policy gate keeps a downgrade from sneaking back in. An SCA tool such as Safeguard can report the exact resolution path so you know which parent dependency to bump. For a deeper look at Java dependency risk, see our Jackson databind security guide.

FAQ

Is CVE-2020-25638 exploitable with default Hibernate settings?

Not through this path. It requires hibernate.use_sql_comments to be enabled, which is off by default, plus the use of attacker-influenced literals in JPA Criteria queries. Verify the setting, but still patch, because configuration can change.

What versions of hibernate-core fix CVE-2020-25638?

Upgrade to 5.3.20.Final on the 5.3 line, or to 5.4.24.Final on the 5.4 line. Versions before those on each line are affected.

What is the impact of CVE-2020-25638?

The advisory describes impact to data confidentiality and integrity. A successful injection could read unauthorized data or tamper with it, and potentially enable further attacks depending on database permissions.

How do I find hibernate-core if it is a transitive dependency?

Run mvn dependency:tree -Dincludes=org.hibernate:hibernate-core for Maven or the equivalent gradle dependencies command, then read the version that actually resolves. On Spring Boot, upgrading the managed BOM is usually the cleanest way to pull in a patched version.

Never miss an update

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