
Runnable Spring Boot and Quarkus reproducer for CVE-2026-85248, a camel-pqc concurrent Signature race causing ML-DSA signature verification bypass, with affected vs fixed builds.
Signature race (signature verification bypass)Runnable proof-of-concept reproducer for the Apache Camel vulnerability where the PQC producer held a single
java.security.Signature instance and used it for every exchange without synchronization. Signature is stateful
and not thread-safe: update() accumulates the data to be signed or verified, and verify()/sign() consume that
accumulated state. With concurrent exchanges sharing one instance the update and verify calls of different messages
interleave, so a verification can complete against data that belongs to another exchange, or against a partially
accumulated buffer. The outcome is non-deterministic and includes a verification reporting success for a message
whose signature was never actually checked, which defeats the guarantee the component exists to provide. Reaching it
requires only concurrent traffic through the same endpoint — the ordinary condition for a Camel route under load.
| Runtime | Directory | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-pqc 4.22.0 (affected; fixed 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.39.0 + camel-quarkus-pqc (Camel 4.22.0, affected; fixed control CQ 3.40.0 / Camel 4.22.1) |
Both modules demonstrate the affected and the fixed behaviour.
A route signs each message with a post-quantum ML-DSA key and then immediately verifies the signature it just
produced, so every legitimately-signed message must verify true. The driver drives 1024 of these sign→verify
round-trips concurrently (16 threads) through the shared pqc: producers.
true — some return false, some raise
signature-engine errors — because the single stateful Signature shared across concurrent exchanges is corrupted by
interleaving. A verdict no longer corresponds to the message it was computed for. (The same race, in the dangerous
direction, lets a verify() succeed for data it never covered.)Signature instance.# Camel Spring Boot
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: many of 1024 broken; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -jar target/cve-2026-85248-pqc-signature-race-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: 0 broken; >>> Not exploited
# Camel Quarkus
cd camel-quarkus
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected (Camel 4.22.0): many broken
docker compose down
# Patched control: CQ 3.40.0 ships Camel 4.22.1
mvn clean package -Dcamel-quarkus.version=3.40.0 -Dquarkus.platform.version=3.40.0
java -jar target/quarkus-app/quarkus-run.jar &
curl -s http://localhost:8080/exploit/attack # fixed: 0 broken
The race is, by nature, timing-dependent; the reproducer drives enough concurrency (1024 round-trips) that it manifests reliably on the affected build. If an affected run ever shows 0 broken, re-run it.
| Property | Value |
|---|---|
| Component | camel-pqc (PQCProducer signature/verification) |
| CWE | CWE-362 (Concurrent Execution using Shared Resource with Improper Synchronization) |
| Severity | MEDIUM |
| Attack vector | Concurrent traffic through the same pqc: endpoint sharing one stateful java.security.Signature |
| Impact | Non-deterministic signature verification; a verify can report success for a message whose signature was never checked |
| Affected Versions | From 4.12.0 before 4.18.5, from 4.19.0 before 4.22.1 |
| Fixed Versions | 4.18.5, 4.22.1, 4.23.0 |
| JIRA | CAMEL-24445 |
| Credit | Claude Security Scan Tool |
Advisory: https://camel.apache.org/security/CVE-2026-85248.html
PQCProducer no longer shares the Signature across concurrent
exchanges. When the producer created the instance itself it now creates a fresh one per exchange
(signerForExchange()); when the user configured a (JVM-wide public static final) instance, access to it is
synchronized. Either way, no two exchanges interleave their init/update/verify sequences on one instance.
Restrict the affected route to a single concurrent consumer so that no two exchanges use the Signature instance at
once.
This repository is published for educational and defensive purposes: to help Apache Camel users understand the vulnerability, verify whether they are affected, and confirm that upgrading resolves it. The messages and keys are inert local fixtures. Do not use this material against systems you do not own or operate.