CVE-2026-42027
Publication date:
04/05/2026
Arbitrary Class Instantiation via Model Manifest in Apache OpenNLP ExtensionLoader<br />
<br />
<br />
<br />
<br />
<br />
Versions Affected: before 2.5.9, before 3.0.0-M3<br />
<br />
<br />
<br />
<br />
<br />
Description: <br />
<br />
The ExtensionLoader.instantiateExtension(Class, String) method loads a class by its fully-qualified name via Class.forName() and invokes its no-arg constructor, with the class name sourced from the manifest.properties entry of a model archive. The existing isAssignableFrom check correctly rejects classes that are not subtypes of the expected extension interface (BaseToolFactory for factory=, ArtifactSerializer for serializer-class-*), but the check runs after Class.forName() has already loaded and initialized the named class. <br />
<br />
Class.forName() with default initialization semantics executes the target class&#39;s static initializer before returning, so an attacker who can supply a crafted model archive can cause the static initializer of any class on the classpath to run during model loading, regardless of whether that class passes the subsequent type check. <br />
<br />
Exploitation requires a class with attacker-useful side effects in its static initializer (for example, JNDI lookup, outbound network I/O, or filesystem access) to be present on the classpath, so this is not a drop-in remote code execution; however, the attack surface grows as third-party model distribution becomes more common (community model repositories, Hugging Face-style sharing), where users routinely load model files from origins they do not control. A secondary, narrower vector affects deployments that ship legitimate BaseToolFactory or ArtifactSerializer subclasses with side-effecting no-arg constructors: a malicious manifest can name such a class and force its constructor to run during model load.<br />
<br />
<br />
<br />
<br />
<br />
Mitigation: <br />
<br />
<br />
<br />
* 2.x users should upgrade to 2.5.9. <br />
* 3.x users should upgrade to 3.0.0-M3. <br />
<br />
<br />
<br />
<br />
Note: The fix introduces a package-prefix allowlist that is consulted before Class.forName() is invoked, so the static initializer of a disallowed class is never executed. Classes under the opennlp. prefix remain permitted by default. Deployments that load models referencing factories or serializers outside opennlp.* must opt those packages in, either programmatically via ExtensionLoader.registerAllowedPackage(String) before the first model load, or by setting the OPENNLP_EXT_ALLOWED_PACKAGES system property to a comma-separated list of allowed package prefixes. <br />
<br />
Users who cannot upgrade immediately should ensure that all model files are sourced from trusted origins and should audit their classpath for classes with side-effecting static initializers or constructors, particularly any that perform JNDI lookups, network requests, or filesystem operations during class initialization.
Severity CVSS v4.0: Pending analysis
Last modification:
05/05/2026