# Patch Analysis: CVE-2026-27654 Fix

## What the Fix Changes

The fix (commit `9739e75` in nginx/nginx, included in releases `1.28.3` and `1.29.7`) adds a single length-validation check in `ngx_http_dav_copy_move_handler()` (`src/http/modules/ngx_http_dav_module.c`) before the code temporarily substitutes `r->uri` with the parsed `Destination` header URI (`duri`) and calls `ngx_http_map_uri_to_path()`.

```c
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

if (clcf->alias
    && clcf->alias != NGX_MAX_SIZE_T_VALUE
    && duri.len < clcf->alias)
{
    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                  "client sent invalid \"Destination\" header: \"%V\"",
                  &dest->value);
    return NGX_HTTP_BAD_REQUEST;
}
```

This rejects any COPY/MOVE request whose destination URI is shorter than the matched location prefix length (`clcf->alias`), preventing the unsigned `size_t` underflow in `ngx_http_map_uri_to_path()`:

```c
path->len = clcf->root.len + reserved + r->uri.len - alias + 1;
```

## Fix Assumptions

1. **The only vulnerable callers of `ngx_http_map_uri_to_path()` with a controllable short URI are in `ngx_http_dav_copy_move_handler()`**: The fix is localized to the DAV COPY/MOVE handler and does not modify `ngx_http_map_uri_to_path()` itself.
2. **All alias locations (except regex aliases) set `clcf->alias` to the location name length**: The fix relies on `clcf->alias` accurately reflecting the prefix length that will be subtracted from `r->uri.len` inside `ngx_http_map_uri_to_path()`.
3. **Regex aliases (`clcf->alias == NGX_MAX_SIZE_T_VALUE`) are safe**: The fix explicitly excludes regex alias locations because `ngx_http_map_uri_to_path()` uses a completely different code path for them (script-based root with `r->add_uri_to_alias`), which does not perform the same subtraction.
4. **The source URI (`r->uri`) is always safe**: The fix does not protect the first `ngx_http_map_uri_to_path()` call (line 706) that maps the source path, because `r->uri` is the original request URI that has already passed location matching.

## What the Fix Does NOT Cover

1. **Other modules or handlers that might temporarily modify `r->uri` before calling `ngx_http_map_uri_to_path()`**: A comprehensive audit was performed across the nginx codebase. Only `ngx_http_dav_copy_move_handler()` temporarily overwrites `r->uri` with attacker-controlled data (`duri`) before calling `ngx_http_map_uri_to_path()`. Other callers (`try_files`, `internal_redirect`, script engine) either modify `r->uri` after the call or restart request processing entirely.
2. **Integer overflow via addition in `ngx_http_map_uri_to_path()`**: The fix only prevents underflow from subtraction (`r->uri.len - alias`). It does not add checks for addition overflow (`clcf->root.len + reserved + ...`), but this is impractical to trigger with 64-bit `size_t`.
3. **Other DAV methods (PUT/DELETE/MKCOL)**: These handlers call `ngx_http_map_uri_to_path()` directly with the original `r->uri`, which is guaranteed by nginx location matching to be at least as long as the location prefix for prefix locations. They are not vulnerable to the same underflow.
4. **Bypass via `NGX_MAX_SIZE_T_VALUE` alias**: The fix explicitly skips regex alias locations. Testing confirmed that regex aliases use a safe path in `ngx_http_map_uri_to_path()` that does not subtract `alias` from `r->uri.len`.

## Testing Results

The fix was tested against multiple variant triggers:

| Variant | Vulnerable (1.29.6) | Fixed (1.29.7) | Verdict |
|---|---|---|---|
| Original: prefix `location /davvvv/` + short Destination | ASAN crash | 400 Bad Request | Fix works |
| Exact match `location = /davvvv` + short Destination | ASAN crash | 400 Bad Request | Fix works |
| Nested location + short Destination | ASAN crash | 400 Bad Request | Fix works |
| Script alias (`alias .../$http_host/`) + short Destination | ASAN crash | 400 Bad Request | Fix works |
| MOVE method + short Destination | ASAN crash | 400 Bad Request | Fix works |
| URL-encoded short Destination (`/%78%78`) | ASAN crash | 400 Bad Request | Fix works |
| Regex alias + short Destination | 500 Internal Error | 500 Internal Error | Not applicable (different path) |

No bypass or true variant that reproduces on the fixed version was discovered.

## Conclusion

The fix is **complete and correct** for the specific vulnerability pattern. It precisely targets the only code path in nginx where an attacker-controlled URI is substituted into `r->uri` before `ngx_http_map_uri_to_path()` is called. All tested alternate triggers on the vulnerable version are caught by the same fix on the fixed version. No bypass was found.
