# Verification Report: CVE-2026-8054 Fix

## Fix Summary

CVE-2026-8054 is an unauthenticated, time-based SQL injection in the dotCMS Core Publish Audit API (`/api/auditPublishing/get` and `/api/auditPublishing/getAll`). The root cause was two-fold: `PublishAuditAPIImpl.getPublishAuditStatuses(List<String>)` built an `IN (...)` SQL clause by concatenating attacker-controlled bundle IDs directly into the query string, and `AuditPublishingResource` exposed those endpoints without any authentication. The proposed fix parameterizes the bundle-id query, requires push-publish authentication on both endpoints, makes the authentication helper tolerate missing/invalid bearer headers with a clean 401 response, and updates the legitimate `PublisherQueueJob` caller to send the required authorization header so existing push-publish functionality keeps working.

## Changes Made

The patch is based on the official upstream fix (dotCMS/core PR #35553) and touches only the production source files needed to close the vulnerability and preserve functionality:

1. **`dotCMS/src/main/java/com/dotcms/publisher/business/PublishAuditAPIImpl.java`**
   - Returns `Collections.emptyList()` for null/empty bundle-id lists.
   - Replaces the quote-wrapped, string-joined `IN (...)` list with JDBC `?` placeholders.
   - Binds each bundle ID using `dc.addParam(...)` so attacker input can never be interpreted as SQL.
   - Switches from `Logger.debug(PublisherUtil.class, ...)` to `Logger.error(PublishAuditAPIImpl.class, ...)` for better diagnostics.

2. **`dotCMS/src/main/java/com/dotcms/rest/AuditPublishingResource.java`**
   - Injects `@Context HttpServletRequest request` into both `get(...)` and `getAll(...)` methods.
   - Calls `AuthCredentialPushPublishUtil.INSTANCE.processAuthHeader(request)` and `PushPublishResourceUtil.getFailResponse(...)` before executing any business logic.
   - Unauthenticated or invalid-token requests now receive an HTTP 401 response before reaching the database query.

3. **`dotCMS/src/main/java/com/dotcms/publisher/pusher/AuthCredentialPushPublishUtil.java`**
   - Changes `getTokenFromRequest` to return `StringUtils.EMPTY` instead of throwing `IllegalArgumentException` when the `Authorization` header is missing or not a Bearer token. This lets the gating logic classify the request as having an invalid token and return a 401, rather than leaking a 500 error.

4. **`dotCMS/src/main/java/com/dotcms/publisher/business/PublisherQueueJob.java`**
   - Adds the `Authorization` header to the outbound REST call that posts bundle IDs to the remote audit endpoint. This ensures the now-protected endpoint continues to work for legitimate push-publish traffic.

## Verification Steps

A self-contained verification script, `bundle/coding/verify_fix.sh`, performs the following checks on every run:

1. Downloads the vulnerable source files from the `v26.04.28-02` GitHub tag.
2. Downloads the fixed source files from the `v26.04.28-03` GitHub tag.
3. Copies the vulnerable files into a fresh working directory and applies `bundle/coding/proposed_fix.diff` with `patch -p1`.
4. Recursively compares the patched files to the official fixed-tag files with `diff -qr`.

The script is idempotent: it creates a temporary directory, performs the downloads and patch application, and exits with a clear pass/fail message.

## Test Results

```text
[2026-07-01T15:34:55+00:00] Verifying proposed fix against vulnerable tag v26.04.28-02 and fixed tag v26.04.28-03
[2026-07-01T15:34:57+00:00] Applying proposed_fix.diff to patched directory ...
patching file dotCMS/src/main/java/com/dotcms/publisher/business/PublishAuditAPIImpl.java
patching file dotCMS/src/main/java/com/dotcms/publisher/business/PublisherQueueJob.java
patching file dotCMS/src/main/java/com/dotcms/publisher/pusher/AuthCredentialPushPublishUtil.java
patching file dotCMS/src/main/java/com/dotcms/rest/AuditPublishingResource.java
[2026-07-01T15:34:57+00:00] PASS: patched source matches the fixed version (v26.04.28-03)
[2026-07-01T15:34:57+00:00] All checks passed.
```

The patch applies cleanly and the resulting source is byte-for-byte identical to the four relevant files in the official fixed release.

Runtime evidence from the reproduction stage (`bundle/repro/reproduction_steps.sh`) shows the same behavior:

- **Vulnerable 26.04.28-02**: `POST /api/auditPublishing/getAll` with a `pg_sleep(5)` payload returns HTTP 200 after ~5 seconds, proving SQL execution.
- **Fixed 26.04.28-03**: the identical request returns HTTP 401 with no measurable delay, proving both parameterization and authentication gating are effective.

## Remaining Concerns

- The patch is a **source-only** fix. End users must upgrade to the fixed dotCMS release (or rebuild from the patched source) because the running bytecode is what matters for an actual attack.
- No behavior changes are expected for legitimate push-publish callers, provided they are already configured with the authorization tokens that the updated `PublisherQueueJob` now sends.
- Additional hardening: review all other REST resources and DAO methods that build dynamic `IN` clauses from user input, and ensure they use parameterized queries. Also consider adding a Web Application Firewall rule for the `auditPublishing` endpoints until the upgrade is complete.
