AI and data stack advisories

Severe, 6 weeks1498Projects326

1498 severe, 6 weeks · 326 projects

AWSGHSA-59g6-234f-frf6

REMOVE_BASE_PATH strips every leading repetition of the base path, not just one

AWS

Published Sep 25, 2026

Low
Fix: upgrade to 1.1.0 or later
GitHub advisory

Summary

AWS_LWA_REMOVE_BASE_PATH is documented as "the base path to be removed from request path" —

singular. In affected versions the implementation removed every leading repetition of it,

because it used str::trim_start_matches rather than str::strip_prefix. The match was also not

anchored to a path-segment boundary, so a partial-segment prefix was stripped too.

src/lib.rs, as of v1.0.1:

```rust

let path = event.raw_http_path().to_string(); // caller-controlled request path

let mut path = path.as_str();

...

if let Some(base_path) = self.base_path.as_deref() {

let stripped = path.trim_start_matches(base_path); // removes ALL leading repetitions

if stripped.len() != path.len() { /* debug log */ }

path = stripped;

}

`

path comes from event.raw_http_path(), so it is under the caller's control. The debug log

compared only stripped.len() != path.len(), so a multi-strip was indistinguishable from a single

strip in the logs.

Behaviour

With AWS_LWA_REMOVE_BASE_PATH=/api:

| request path | affected versions | fixed (v1.1.0) |

|---|---|---|

| /api/orders | /orders | /orders |

| /api/api/admin | **/admin** | /api/admin |

| /api/api/api/internal | **/internal** | /api/api/internal |

| /apiorder | **order** | /apiorder |

Impact

The common deployment shape is an edge (API Gateway / ALB / CloudFront) that exposes...

Affected versions

PackageAffectedFixed in
aws-lambda-web-adapter
Product
< 1.1.01.1.0
Details and references

## Summary `AWS_LWA_REMOVE_BASE_PATH` is documented as "the base path to be removed from request path" — singular. In affected versions the implementation removed **every** leading repetition of it, because it used `str::trim_start_matches` rather than `str::strip_prefix`. The match was also not anchored to a path-segment boundary, so a partial-segment prefix was stripped too. `src/lib.rs`, as of v1.0.1: ```rust let path = event.raw_http_path().to_string(); // caller-controlled request path let mut path = path.as_str(); ... if let Some(base_path) = self.base_path.as_deref() { let stripped = path.trim_start_matches(base_path); // removes ALL leading repetitions if stripped.len() != path.len() { /* debug log */ } path = stripped; } ``` `path` comes from `event.raw_http_path()`, so it is under the caller's control. The debug log compared only `stripped.len() != path.len()`, so a multi-strip was indistinguishable from a single strip in the logs. ## Behaviour With `AWS_LWA_REMOVE_BASE_PATH=/api`: | request path | affected versions | fixed (v1.1.0) | |---|---|---| | `/api/orders` | `/orders` | `/orders` | | `/api/api/admin` | **`/admin`** | `/api/admin` | | `/api/api/api/internal` | **`/internal`** | `/api/api/internal` | | `/apiorder` | **`order`** | `/apiorder` | ## Impact The common deployment shape is an edge (API Gateway / ALB / CloudFront) that exposes only a prefix — `/api/*` — and forwards to a Lambda running the adapter, which strips that prefix before handing the request to the app. Under that shape an operator may assume the app's routes outside the prefix are unreachable from the internet. A request for `/api/api/admin` satisfies the edge's `/api/*` rule, and the adapter then removed the prefix twice, so the application received `/admin`. With the documented single-strip behaviour it would have received `/api/admin`. Whether that reaches anything sensitive depends entirely on the application's routing, so this is not a universal-impact issue and no bypass exists inside the adapter itself. The defect is that the adapter did not do what its own documentation said, in a direction that only ever exposes *more* of the backend than intended, driven by the request path. Applications should not rely on an edge prefix rule as their only control over which routes are reachable. ## Patches Fixed in **v1.1.0**. The adapter now strips exactly one leading occurrence, only on a path-segment boundary, and normalizes a configured trailing slash first: ```rust if let Some(base_path) = self.base_path.as_deref() { let base_path = base_path.strip_suffix('/').unwrap_or(base_path); if let Some(rest) = path.strip_prefix(base_path) { if rest.is_empty() || rest.starts_with('/') { path = if rest.is_empty() { "/" } else { rest }; } } } ``` **Operators upgrading from 1.0.1 or earlier should verify their routes** if they relied on the old repeated or partial-segment stripping behaviour. This is a deliberate behaviour change and is also noted in the v1.1.0 release notes. ## Workarounds On affected versions, make the edge reject request paths that repeat the base path segment, or unset `AWS_LWA_REMOVE_BASE_PATH` and let the application serve its routes under the full prefix. ## Verification The reported behaviour was measured against the two Rust standard-library functions directly, not against a deployed Lambda + API Gateway stack. The fix is covered by a regression test in `src/lib.rs` (`test_base_path_strip_single_and_segment_aware`) pinning single-occurrence, segment-aware, exact-match and trailing-slash cases.

Severity from
GitHub (reviewed advisory)
Weakness
CWE-436

More AWS advisories

All AWS