Skip to content

chore(deps): bump com.cedarsoftware:java-util from 4.108.0 to 4.109.0 - #1882

Closed
dependabot[bot] wants to merge 1 commit into
t8from
dependabot/maven/t8/com.cedarsoftware-java-util-4.109.0
Closed

chore(deps): bump com.cedarsoftware:java-util from 4.108.0 to 4.109.0#1882
dependabot[bot] wants to merge 1 commit into
t8from
dependabot/maven/t8/com.cedarsoftware-java-util-4.109.0

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Jul 27, 2026

Copy link
Copy Markdown
Contributor

Bumps com.cedarsoftware:java-util from 4.108.0 to 4.109.0.

Release notes

Sourced from com.cedarsoftware:java-util's releases.

4.109.0

java-util 4.109.0 — Security release

This release fixes a critical remote-code-execution path. It was reported against json-io 4.108.0, but the defect is here: json-io performs no security checks of its own — it reads a class name from untrusted input (a JSON @type) and delegates instantiation to ClassUtilities.newInstance(), whose denylist is the sole gate.

Released in lock-step with json-io 4.109.0, which pins this version.

The vulnerability was an unenforced check, not an incomplete denylist

newInstance() routes a Map of named arguments to newInstanceWithNamedParameters(), which never called SecurityChecker.verifyClass() — only the positional fallback did. A class the checker itself reported as blocked was constructed anyway:

isSecurityBlocked(EvilLoader) = true      // a ClassLoader subclass — denylisted
>>> EvilLoader ctor ran                   // constructed regardless

The reported exploit named org.springframework.context.support.ClassPathXmlApplicationContext, whose varargs String... configLocations constructor calls refresh() — loading attacker-supplied bean XML that instantiates ProcessBuilder with init-method="start" inside a Spring child context, beyond the gate's reach. Because the payload arrived as a named parameter, it flowed entirely through the unchecked path.

Adding the gadget class to the denylist would not have closed the reported PoC. The enforcement hole was the vulnerability. The same primitive also reached java.net.Socket (SSRF) and java.io.FileOutputStream (arbitrary file create/truncate) using nothing outside java.base.

What changed

  • The gate is enforced at the single public chokepoint, outside every try — a SecurityException raised deeper was being swallowed by fallback handlers that retry on Exception — and re-asserted on the named-parameter path.
  • verifyClass() now applies blocked-package prefixes. They previously lived only in isSecurityBlockedName() and applied only when loading by name, so a class already in hand from a blocked package passed. Identity, name, prefix, and supertype checks are now unified across both the class-resolution and instantiation layers.
  • The enclosing class of an inner class gets its own verdict — it is constructed too, and was ungated.
  • The denylist covers gadget families by supertype name, so one entry catches every implementation without java-util depending on the library: ApplicationContext/BeanFactory (all Spring contexts), JNDI, javax.xml.transform.Templates, ObjectInputStream, constructors performing network I/O or creating/truncating files, Rhino/BeanShell/Jython/GroovyShell, and java.rmi./javax.management.remote./jdk.internal..

Read-side file I/O (FileInputStream, FileReader) is deliberately still constructible — opening a read handle is not a side effect on the order of spawning a process. java.lang.invoke.MethodHandle/MethodHandles were deliberately not added: both are non-instantiable, so blocking them would only break resolution of an ordinary MethodHandle-typed field. MethodHandles$Lookup, which grants reflective module-opening power, remains blocked.

New configuration

Expanding a denylist can break a consumer who legitimately constructs one of these types, so the list is now adjustable:

ClassUtilities.SecurityChecker.addBlockedClass("com.acme.Danger");
ClassUtilities.SecurityChecker.addBlockedPackage("com.acme.unsafe.");
ClassUtilities.SecurityChecker.allowClass("java.io.FileOutputStream");  // at your own risk

Plus the classutilities.security.blocked.classes, classutilities.security.blocked.packages, and classutilities.security.unblocked system properties. Precedence: an explicit unblock wins, then any blocking rule, then allowed. Programmatic rules are consulted ahead of the ClassValue verdict cache, so they take effect immediately for already-checked classes; the default configuration adds one volatile boolean read.

Upgrading

No API changes and no behavioral change for ordinary use. Pinned by 14 new tests that reproduce the reported payload against a dependency-free stand-in for ClassPathXmlApplicationContext — same varargs constructor and constructor side effect, compiled with -parameters as Spring's own jars are, so the tests cannot pass for the wrong reason.

All 20,376 java-util tests pass, as do all 4,748 json-io 4.109.0 tests (both Spring modules included) against this build.


Full changelog: https://github.com/jdereg/java-util/blob/master/changelog.md

Changelog

Sourced from com.cedarsoftware:java-util's changelog.

4.109.0 - 2026-07-26

  • SECURITY (critical): ClassUtilities.newInstance() did not enforce its own denylist on the named-parameter path — fixes the constructor-injection RCE reported against json-io 4.108.0. json-io performs no security checks of its own; it reads a class name from untrusted input (@type) and delegates instantiation here, so the fix belongs in java-util. Released in lock-step with json-io 4.109.0.
    • The enforcement hole (the actual vulnerability). newInstance(Converter, Class, Object) routes a Map of arguments to newInstanceWithNamedParameters(), which never called SecurityChecker.verifyClass() — only the positional fallback did. A class the checker itself reported as blocked was therefore constructed anyway: isSecurityBlocked(EvilLoader) == true (a ClassLoader subclass, blocked via the supertype walk) while newInstance(EvilLoader.class, {"marker": ...}) ran its constructor. The report characterized the defect as an incomplete denylist, but the reported PoC flowed entirely through this unchecked path, so adding the gadget class to the list would not have closed it. The check now happens once at the public entry point, outside every try (a SecurityException raised deeper down was being swallowed by the fallback handlers that retry on Exception), and is re-asserted inside newInstanceWithNamedParameters as defense in depth. Specifically, ClassPathXmlApplicationContext(String... configLocations) was reachable because the varargs branch of named matching widens a single attacker string into a String[1], so every parameter matched and the constructor fired refresh() — fetching the attacker's bean XML and instantiating ProcessBuilder with init-method="start" inside a Spring child context, beyond this gate's reach.
    • verifyClass() ignored the blocked-package prefixes. The prefix rules (javax.script., jdk.nashorn.) lived only in isSecurityBlockedName() and were consulted only when loading by name; a class already in hand from a blocked package passed. Name, identity, prefix, and supertype checking are now unified behind one gate used by both the loading and instantiation paths.
    • The enclosing class of an inner class was constructed ungated (newInstance instantiates it to supply the outer instance). It now gets its own verdict, verified outside the surrounding catch-all that would otherwise downgrade the refusal into a silent fall-through.
    • Denylist expanded to cover the gadget families, listed by interface/supertype name so one entry covers every implementation, present or future, without java-util depending on the library: indirect loaders (org.springframework.context.ApplicationContext, org.springframework.beans.factory.BeanFactory), JNDI (javax.naming., com.sun.jndi., com.sun.rowset.JdbcRowSetImpl), bytecode carriers (javax.xml.transform.Templates, com.sun.org.apache.xalan.), java.io.ObjectInputStream, constructors that perform network I/O (Socket, ServerSocket, DatagramSocket, URLConnection) or create/truncate a file (FileOutputStream, FileWriter, RandomAccessFile), further scripting engines (Rhino, BeanShell, Jython, groovy.lang.GroovyShell), and java.rmi./javax.management.remote./jdk.internal.. Read-side file I/O (FileInputStream, FileReader) is deliberately left constructible — opening a read handle is not a side effect on the order of spawning a process or truncating a file. java.lang.invoke.MethodHandle/MethodHandles were deliberately not added: both are non-instantiable (abstract / no public constructor), so blocking them would only break resolution of an ordinary MethodHandle-typed field; MethodHandles$Lookup, the object that actually grants reflective module-opening power, remains blocked.
    • New configuration, because expanding a denylist can break a consumer who legitimately constructs one of these types: SecurityChecker.addBlockedClass(String), addBlockedPackage(String), allowClass(String), and clearSecurityOverrides(), plus the classutilities.security.blocked.classes, classutilities.security.blocked.packages, and classutilities.security.unblocked system properties. Precedence is an explicit unblock first, then any blocking rule, then allowed. allowClass overrides built-ins and is documented as at-your-own-risk. Programmatic rules are consulted ahead of the ClassValue verdict cache, which is what lets them take effect immediately for already-checked classes with no invalidation machinery; the default configuration (no programmatic rules) adds one volatile boolean read to the pre-existing lookup.
    • Pinned by 14 new tests that reproduce the reported payload against a dependency-free stand-in for ClassPathXmlApplicationContext — shaped with the same varargs constructor and constructor side effect, and compiled with -parameters as Spring's own jars are, so name matching really is viable and the test cannot pass for the wrong reason. All 20,376 tests pass, as do all 4,748 json-io 4.109.0 tests (both Spring modules included) against this build.
  • BUILD: json-io test-scope dependency 4.107.0 → 4.108.0 (the "latest released json-io minus 1" rule shifts forward now that json-io 4.108.0 is out). Test scope only — no consumer-facing surface.
Commits
  • 7475bca Fix: preflight's zscaler check passed straight through zscaler
  • aa7cf8e Security: newInstance() did not enforce its denylist on the named-parameter path
  • See full diff in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [com.cedarsoftware:java-util](https://github.com/jdereg/java-util) from 4.108.0 to 4.109.0.
- [Release notes](https://github.com/jdereg/java-util/releases)
- [Changelog](https://github.com/jdereg/java-util/blob/master/changelog.md)
- [Commits](jdereg/java-util@4.108.0...4.109.0)

---
updated-dependencies:
- dependency-name: com.cedarsoftware:java-util
  dependency-version: 4.109.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file java Pull requests that update Java code labels Jul 27, 2026
@nmaguiar

Copy link
Copy Markdown
Collaborator

@dependabot rebase

@dependabot @github

dependabot Bot commented on behalf of github Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Looks like com.cedarsoftware:java-util is up-to-date now, so this is no longer needed.

@dependabot dependabot Bot closed this Jul 28, 2026
@dependabot
dependabot Bot deleted the dependabot/maven/t8/com.cedarsoftware-java-util-4.109.0 branch July 28, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file java Pull requests that update Java code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant