Skip to content
AWSGHSA-59g6-234f-frf6

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

LowPublished Sep 25, 2026

## 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/a...

GitHub advisory

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
Advisory
Type confusion in AWS pgcollection allows remote code execution
High8.8Sep 24
Kiro IDE Insufficient File Write Restrictions to Execution-Sensitive Paths
High8.8Sep 22
Amazon Aurora PostgreSQL a fully managed relational database engine that's compatible...
High8.0Sep 22
HTTPS Fallback to HTTP in Graph Explorer
Medium5.9Sep 22
Code Injection via Improper Triple-Quote Escaping in AgentCore CLI Bedrock Agent Import
Critical9.0Sep 22
Issue with HTTP/2 multi-frame request body inspection in AWS WAF
Critical9.8Sep 22

Critical advisories by email

Wednesdays: the week’s critical and high advisories in the AI and data stack, with the fixed versions. Only in weeks that have some.

Double opt-in. Unsubscribe any time.