{
  "variant_id": "CVE-2026-43825-variant-dos-memexhaust-opennlp-svmdoccat",
  "created_at": "2026-07-09T18:23:00Z",
  "variant_summary": "Memory-exhaustion denial-of-service bypass of the 3.0.0-M4 fix for CVE-2026-43825, reproducing on the FIXED build (opennlp-3.0.0-M4, commit 3cf42d4a). The fix's ObjectInputFilter allow-lists java.util.HashMap and java.lang.String, allows any primitive array up to maxArrayLength (10,000,000), and bounds per-array length and total reference count (maxRefs=5,000,000) but NOT total allocated memory. A HashMap<String,double[8_000_000]> with a few entries is entirely allow-listed and within every numeric limit, yet deserialising it allocates n*64MiB during ObjectInputStream.readObject()->HashMap.readObject()->readArray, throwing OutOfMemoryError on a constrained heap BEFORE the cast to SvmDoccatModel. The filter does NOT reject this stream (large-heap run completes all allocations then fails only at the cast with ClassCastException, never InvalidClassException). Impact class is denial_of_service, NOT the original CVE's code_execution. The fix's PRIMARY goal (block foreign-gadget RCE) still holds: a MaliciousGadget stream is rejected with InvalidClassException (filter status: REJECTED) on the fixed build and no gadget code runs. An RCE bypass via the allow-list was ruled out: every allow-listed class (OpenNLP/zlibsvm de.hhn.mi.*/libsvm/JDK primitives + HashMap + String) is a plain data/record/enum/struct type with no exploitable readObject/readResolve/writeReplace hook (verified by bytecode inspection).",
  "relation": "newer_version_sibling",
  "origin_kind": "pruva_variant",
  "repository": "https://github.com/apache/opennlp",
  "submitted_target": {
    "target_kind": "git_commit",
    "commit_sha": "3cb7232ecaccc788e32bf76b7c031fb166840da5",
    "version": "3.0.0-SNAPSHOT (pre-3.0.0-M4)",
    "ref": "3cb7232e",
    "display": "apache/opennlp@3cb7232e (parent of fix; pre-3.0.0-M4; vulnerable to RCE per CVE-2026-43825)"
  },
  "variant_target": {
    "target_kind": "git_commit",
    "commit_sha": "3cf42d4a0145cefd9dd06138873a91312052c767",
    "version": "3.0.0-M4",
    "ref": "3cf42d4a",
    "display": "apache/opennlp@3cf42d4a (tag opennlp-3.0.0-M4; fixed for RCE; DoS bypass reproduces here)"
  },
  "same_root_cause_confidence": "high",
  "same_surface_confidence": "high",
  "claimed_surface": "library_api",
  "validated_surface": "library_api",
  "required_entrypoint_kind": "function_call",
  "required_entrypoint_detail": "opennlp.tools.ml.libsvm.doccat.SvmDoccatModel.deserialize(InputStream) in org.apache.opennlp:opennlp-ml-libsvm (same public static entry point as the parent CVE)",
  "attacker_controlled_input": "Crafted Java serialized byte stream composed ONLY of allow-listed classes: a top-level java.util.HashMap<String, double[]> whose values are primitive double arrays of length <= 10,000,000 (== maxArrayLength). The stream is supplied to SvmDoccatModel.deserialize(InputStream).",
  "trigger_path": "attacker stream (HashMap<String,double[<=10M]>) -> SvmDoccatModel.deserialize(InputStream) [line 235] -> deserialize(InputStream,DeserializationLimits) [line 261] -> ois.setObjectInputFilter(buildFilter(limits)) [line 270] -> filter ALLOWS (HashMap, String allow-listed; double[] primitive-allowed; arrayLength<=10M; refs<=5M) -> ois.readObject() [line 271] -> ObjectInputStream.readObject -> HashMap.readObject -> readArray -> Array.newInstance allocates n*L*8 bytes -> OutOfMemoryError (memory-exhaustion DoS) before cast to SvmDoccatModel",
  "observed_impact_class": "denial_of_service",
  "exploitability_confidence": "high",
  "evidence_scope": "realistic_harness",
  "runtime_manifest_present": true,
  "end_to_end_target_reached": true,
  "inferred": false,
  "claim_block_reason": null,
  "blocking_mitigation": null,
  "file_path": "opennlp-core/opennlp-ml/opennlp-ml-libsvm/src/main/java/opennlp/tools/ml/libsvm/doccat/SvmDoccatModel.java",
  "line_start": 366,
  "line_end": 382,
  "secondary_anchors": [
    {
      "file_path": "opennlp-core/opennlp-ml/opennlp-ml-libsvm/src/main/java/opennlp/tools/ml/libsvm/doccat/SvmDoccatModel.java",
      "line_start": 261,
      "line_end": 271
    },
    {
      "file_path": "opennlp-core/opennlp-ml/opennlp-ml-libsvm/src/main/java/opennlp/tools/ml/libsvm/doccat/SvmDoccatModel.java",
      "line_start": 325,
      "line_end": 358
    }
  ],
  "review_scope_paths": [
    "opennlp-core/opennlp-ml/opennlp-ml-libsvm/src/main/java/opennlp/tools/ml/libsvm/doccat/SvmDoccatModel.java"
  ],
  "artifact_refs": {
    "variant_manifest": "bundle/vuln_variant/variant_manifest.json",
    "validation_verdict": "bundle/vuln_variant/validation_verdict.json",
    "runtime_manifest": "bundle/vuln_variant/runtime_manifest.json",
    "repro_log": "bundle/logs/vuln_variant/fixed_oom_small.log",
    "root_cause_equivalence": "bundle/vuln_variant/root_cause_equivalence.json",
    "reproducer": [
      "bundle/vuln_variant/reproduction_steps.sh",
      "bundle/vuln_variant/harness/Variant.java"
    ]
  }
}
