# Verification Report — CVE-2026-40022 (camel-platform-http-main)

## Fix Summary

The vulnerability is an authentication bypass in Apache Camel's embedded
HTTP/management server (`camel-platform-http-main`). When a non-root context
path (e.g. `/api`, `/admin`) is configured, the authentication handler is
registered on the Vert.x **sub-router**, which matches paths **relative** to the
consumed context prefix. The vulnerable code derived the auth-protected path
from the context path itself (only special-casing the exact root `/`), so the
handler ended up at an exact path (e.g. `/api`) that — as a *relative* sub-router
path — matches only `/api/api`, never the real subpaths (`/api/hello`). The
official 4.14.6 fix corrected only the **default** (unset) case by resolving to
`/*`, but returned any **explicit** `authenticationPath` verbatim; because the
user-facing Javadoc describes `authenticationPath` in absolute-URL-path terms,
operators are encouraged to set it to the context prefix (e.g.
`camel.server.authenticationPath=/api`), which silently downgrades protection to
zero on the *patched* build (the incomplete-fix variant).

This fix centralizes path resolution in a new
`MainAuthenticationConfigurer.resolveAuthenticationPath(authenticationPath, contextPath)`
default method and makes both `BasicAuthenticationConfigurer` and
`JWTAuthenticationConfigurer` (each with server + management overloads) call it.
The resolver (a) defaults an **unset** `authenticationPath` to `/*` (closes the
original CVE), and (b) **normalizes an explicit value that equals or starts with
the context path**: it strips the context prefix and widens a whole-context
remainder (`/api`, `/api/*`, `/`) to `/*` so "protect the context" actually
protects every subpath (closes the explicit-prefix variant), while a genuine
relative sub-path such as `/secure/*` is preserved unchanged for selective
protection. This is a strict superset of the upstream fix and also closes the
incomplete-fix variant that reproduces on 4.14.6.

## Changes Made

All changes are in
`components/camel-platform-http-main/src/main/java/org/apache/camel/component/platform/http/main/authentication/`
(patch `bundle/coding/proposed_fix.diff`, 3 files, +39/−20):

1. **`MainAuthenticationConfigurer.java`**
   - Added `import org.apache.camel.util.ObjectHelper;`
   - Added `default String resolveAuthenticationPath(String authenticationPath, String contextPath)`:
     - returns `/*` when `authenticationPath` is empty/null (CVE-2026-40022 default case);
     - for a non-empty explicit value, strips the context prefix when the value
       equals `contextPath` or starts with `contextPath + "/"` (and `contextPath`
       is not `/`), then widens an empty/`/` remainder to `/*` (explicit-prefix
       variant), otherwise returns the (possibly stripped) relative path
       unchanged (preserves selective protection such as `/secure/*`).
   - Documented the relative-to-context semantics and the unset = protect-all
     behavior in the method Javadoc.

2. **`BasicAuthenticationConfigurer.java`**
   - Removed the now-unused `import static ... ObjectHelper.isNotEmpty;`
   - Both `configureAuthentication(...)` overloads (server + management) replaced
     the inline `isNotEmpty(...) ? ... : properties.getPath()` resolution and the
     `"/".equals(path)` widening with a single call to
     `resolveAuthenticationPath(properties.getAuthenticationPath(), properties.getPath())`.

3. **`JWTAuthenticationConfigurer.java`**
   - Removed the now-unused `import static ... ObjectHelper.isNotEmpty;`
   - Both `configureAuthentication(...)` overloads (server + management) replaced
     the inline resolution + `"/".equals(path)` widening with the same
     `resolveAuthenticationPath(...)` call.

No other production files are touched. The change is behavior-preserving for the
already-correct root-context case (`/` → `/*`) and for deliberate selective
configurations (`/secure/*`).

## Verification Steps

`bundle/coding/verify_fix.sh` is self-contained and idempotent. It:

1. Builds a minimal Camel `Main` application (routes `platform-http:/hello`,
   `/secure/data`, `/public`) against the **vulnerable**
   `camel-platform-http-main:4.14.5` using the shared Maven cache.
2. Materializes the original 4.14.5 authentication sources from the published
   sources jar, applies `proposed_fix.diff` with `patch -p1`, and compiles the 3
   patched classes against the 4.14.5 dependency classpath.
3. Builds a **patched** `camel-platform-http-main` jar by extracting the original
   4.14.5 jar and replacing the 3 authentication `.class` files, then runs the
   **real** embedded Vert.x/Netty HTTP server with that patched jar on the
   classpath (original jar removed to avoid ambiguity).
4. Exercises the full scenario matrix with `curl` over localhost and asserts HTTP
   status codes.

### Commands run

```
patch -p1 < bundle/coding/proposed_fix.diff          # applies cleanly (exit 0)
javac -cp <4.14.5 deps> <3 patched sources>          # compiles cleanly
java -cp target/classes:patched.jar:<deps> repro.App # real embedded server
curl -s -o /dev/null -w "%{http_code}" http://localhost:8090/<path>
bash bundle/coding/verify_fix.sh                     # PASS=12 FAIL=0, exit 0
```

### Test results (patched 4.14.5, real embedded server)

| SC | Config (ctx, authPath) | Path | Creds | Expect | Got | Result |
|----|------------------------|------|-------|--------|-----|--------|
| A | `/api`, unset | `/api/hello` | no | 401 | 401 | PASS |
| A | `/api`, unset | `/api/hello` | yes | 200 | 200 | PASS |
| A | `/api`, unset | `/api/public` | no | 401 | 401 | PASS |
| B | `/api`, `/api` (variant) | `/api/hello` | no | 401 | 401 | PASS |
| B | `/api`, `/api` (variant) | `/api/hello` | yes | 200 | 200 | PASS |
| C | `/api`, `/api/*` (variant) | `/api/hello` | no | 401 | 401 | PASS |
| C | `/api`, `/api/*` (variant) | `/api/hello` | yes | 200 | 200 | PASS |
| D | `/api`, `/secure/*` (selective) | `/api/secure/data` | no | 401 | 401 | PASS |
| D | `/api`, `/secure/*` (selective) | `/api/secure/data` | yes | 200 | 200 | PASS |
| D | `/api`, `/secure/*` (selective) | `/api/public` | no | 200 | 200 | PASS |
| E | `/`, unset (root ctx) | `/hello` | no | 401 | 401 | PASS |
| E | `/`, unset (root ctx) | `/hello` | yes | 200 | 200 | PASS |

**PASS=12 FAIL=0** — exit 0.

### Before/after contrast (variant, scenario B)

`bundle/coding/verify_contrast.log` — identical app + config
(`camel.server.path=/api`, `camel.server.authenticationPath=/api`), only the jar
differs:

```
UNPATCHED camel-platform-http-main 4.14.5 : no_creds=200 with_creds=200   (bypass)
PATCHED   (proposed_fix.diff applied)     : no_creds=401 with_creds=200   (closed)
```

This directly demonstrates the fix changes behavior: the doc-encouraged
explicit-`authenticationPath`-equals-context configuration, which bypasses
authentication on the unpatched build, is now rejected with `401` while valid
credentials still succeed (`200`).

### Edge cases covered

- **Original CVE (default/unset)** on non-root context → now `401` (was `200`).
- **Variant: explicit `authenticationPath=/api`** (equals context) → now `401`.
- **Variant: explicit `authenticationPath=/api/*`** (context + wildcard) → now `401`.
- **Selective protection `/secure/*`** preserved → `/api/secure/data` `401`,
  `/api/public` `200` (no over-broadening).
- **Root context `/`** (unset) → `/hello` `401` (regression-safe).
- **Credentials** accepted in every scenario (`200`) — authentication is
  genuinely enabled and routes are healthy; the fix does not break legit access.

## Remaining Concerns

- **Scope of this patch.** It fixes the authentication-path resolution in
  `camel-platform-http-main` for both the embedded HTTP server and the embedded
  management server (the same `*AuthenticationConfigurer` classes and
  `resolveAuthenticationPath` serve both `HttpServerConfigurationProperties` and
  `HttpManagementServerConfigurationProperties` overloads). The management
  `/observe/info` info-disclosure endpoint shares the identical code path and is
  therefore protected by the same change.
- **Documentation footgun (recommended follow-up, not in this patch).** The
  Javadoc on `HttpServerConfigurationProperties.setAuthenticationPath` /
  `HttpManagementServerConfigurationProperties.setAuthenticationPath` (in the
  `camel-main` module) still reads "Set HTTP url path of embedded server that is
  protected by authentication configuration", which invites the
  absolute-URL-path misconfiguration. A companion doc change clarifying that the
  path is *relative to the context path*, that a wildcard is required to protect
  subpaths, and that unset = protect everything under the context would close the
  footgun at the source. It is intentionally left out of this minimal security
  patch to keep the change scoped to the behavioral fix and avoid spanning a
  second Maven module; the normalization makes the configuration safe regardless
  of the wording.
- **Contrived non-prefix collisions** (e.g. `authenticationPath=/apiv2` with
  context `/api`) are preserved as the operator's explicit relative choice; they
  are not a context-prefix footgun and are out of scope.
- **Operators on unaffected/unfixable releases** should, as defense in depth,
  set `camel.server.authenticationPath=/*` /
  `camel.management.authenticationPath=/*` explicitly; this patch makes that
  unnecessary but harmless.
