
Runnable Spring Boot and Quarkus proof-of-concept for CVE-2026-85243, demonstrating the Apache Camel camel-crypto-pgp integrity-verification downgrade and its fix.
Runnable proof-of-concept reproducer for the Apache Camel vulnerability where the PGP data format's unmarshal()
verified the modification detection code only when the message used the OpenPGP symmetrically encrypted integrity
protected data packet. The older symmetrically encrypted data packet carries no such code, and OpenPGP's CFB mode
is malleable without one, so a message using that legacy packet skipped the integrity check altogether. Because
the packet type is chosen by whoever produced the message, the sender — or anyone able to rewrite the message in
transit — decided whether the integrity check applied at all. The existing integrity option governs marshalling
only and had no decrypt-side counterpart, so a deployment could not require integrity protection on the messages it
accepted.
| Runtime | Directory | Stack |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-crypto-pgp 4.22.0 (affected; fixed 4.22.1) |
| Camel Quarkus | camel-quarkus/ | Quarkus 3.29.0 + camel-quarkus-crypto-pgp (Camel 4.15.0, affected; fixed control CQ 3.40.0 / Camel 4.22.1) |
Both modules demonstrate the affected and the fixed behaviour.
The exploit driver plays a sender (or an intermediary) who produces a PGP message with the legacy packet by
encrypting with integrity=false — the resulting ciphertext carries no modification detection code. It then feeds
that message to a route that decrypts it with the secret key.
BENIGN-PGP-PAYLOAD-MARKER-5E1F) returned — the integrity
check was skipped entirely because the sender chose the legacy packet. The deployment accepted ciphertext it could
not verify.PGPException — "PGP message is not integrity protected…" —
because the new requireIntegrityProtection option defaults to true.The keyrings (pubring.gpg, secring.gpg, user id and password both sdude) are the public RSA-2048 test fixtures
from Apache Camel's own camel-crypto-pgp tests — inert material, bundled so the round-trip is self-contained.
# Camel Spring Boot
cd camel-spring-boot
mvn clean package
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack # affected: legacy message decrypts; >>> PROVEN
docker compose down
# Patched control
mvn clean package -Dcamel.version=4.22.1
java -jar target/cve-2026-85243-crypto-pgp-integrity-downgrade-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack # fixed: rejected "not integrity protected"; >>> 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.15.0): legacy message decrypts
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: rejected "not integrity protected"
| Property | Value |
|---|---|
| Component | camel-crypto-pgp (PGPKeyAccessDataFormat.unmarshal) |
| CWE | CWE-354 (Improper Validation of Integrity Check Value) |
| Severity | MEDIUM |
| Attack vector | A message produced with the legacy symmetrically encrypted data packet (no modification detection code) |
| Impact | Integrity-verification downgrade: the sender/intermediary decides whether the integrity check runs; malleable ciphertext is accepted without verification |
| Affected Versions | From 4.0.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-24441 |
| Credit | Claude Security Scan Tool |
Advisory: https://camel.apache.org/security/CVE-2026-85243.html
PGPKeyAccessDataFormat.unmarshal adds a requireIntegrityProtection
option (default true). When a message is not an integrity protected packet and the option is enabled, unmarshal
now throws PGPException("PGP message is not integrity protected…") instead of decrypting it. Note that
signatureVerificationOption still defaults to optional, so a message carrying no signature is still accepted; the
two options together are what give a decrypted message authenticity and not only confidentiality. Set
requireIntegrityProtection=false only to interoperate with a sender that still emits the legacy packet, and treat the
decrypted content as unauthenticated.
Reject messages that do not use the integrity protected packet before they reach the data format (for example, inspect
the OpenPGP packet header in a processor ahead of unmarshal).
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 keyrings and plaintext are inert public test fixtures. Do not use this material against systems you do not own or operate.