Skip to content

fix: sanitize control bytes in x-amzn-{request,lambda}-context headers#734

Merged
bnusunny merged 6 commits into
mainfrom
fix/issue-732-sanitize-control-bytes-header
May 28, 2026
Merged

fix: sanitize control bytes in x-amzn-{request,lambda}-context headers#734
bnusunny merged 6 commits into
mainfrom
fix/issue-732-sanitize-control-bytes-header

Conversation

@bnusunny

Copy link
Copy Markdown
Contributor

Summary

  • Strip C0 control bytes (< 0x20 except \t) and DEL (0x7F) from the JSON serialized into x-amzn-request-context and x-amzn-lambda-context before constructing HeaderValue. RFC 7230 forbids these bytes in header field values.
  • Adds a unit test for the sanitizer and a regression test that builds an ApiGatewayV2 event with control bytes (0x04, 0x7F, 0x18) in requestContext.http.path and asserts the forwarded request carries a header-safe, JSON-parseable x-amzn-request-context.

Fixes #732.

Why

The reporter's Lambda (behind CloudFront → Function URL) returns 5xx every time nuclei probes it with paths like /%04%7F%18;{curl,...}; because the adapter copies requestContext.http.path verbatim into a JSON header value. http::HeaderValue::from_bytes then rejects the bytes and the whole invocation fails — tripping alarms on traffic that is otherwise harmless and well-formed at the HTTP layer.

Test plan

  • cargo test --lib — 23 passed (was 21, +2 new)
  • cargo clippy --lib --tests -- -D warnings clean
  • Verified the regression test catches the bug: temporarily reverted the sanitizer call and confirmed the new test fails with InvalidHeaderValue, then restored it and confirmed it passes

bnusunny added 2 commits May 27, 2026 17:26
Strip C0 control bytes (< 0x20 except \t) and DEL (0x7F) from the JSON
serialized into the x-amzn-request-context and x-amzn-lambda-context
headers before constructing HeaderValue. RFC 7230 forbids these bytes
in header field values, and the request context echoes the original
request path verbatim — so a Lambda Function URL probed by a security
scanner with crafted paths (e.g. nuclei) would fail every invocation
with InvalidHeaderValue, tripping alarms on otherwise-fine traffic.

Fixes #732
@bnusunny bnusunny force-pushed the fix/issue-732-sanitize-control-bytes-header branch from fec0158 to 65da5fb Compare May 27, 2026 17:46
@seshubaws

Copy link
Copy Markdown

Can we add a test for a parallel assertion for x-amzn-lambda-context, since both call sites changed. And a test for the all-clean fast path (worth covering once the signature is Cow-based).

And maybe we can assert that the stripped JSON still deserializes back into the original RequestContext type, not just into serde_json::Value.

Comment thread src/lib.rs Outdated
bnusunny added 4 commits May 27, 2026 22:44
Helps diagnose mis-configured AWS_LWA_REMOVE_BASE_PATH: only fires when
the prefix actually matched (stripped length differs from original), so
unmatched requests stay quiet.
- Switch strip_forbidden_header_bytes to Cow<'_, [u8]>: header-safe
  input (the common case) skips allocation, and the fast path becomes
  observable in tests via Cow::Borrowed.
- New test_strip_forbidden_header_bytes_all_clean asserts the borrowed
  fast path for clean input.
- Existing unit test now asserts Cow::Owned on the stripping branch.
- Regression test parses the sanitized x-amzn-request-context back into
  the typed RequestContext (not just serde_json::Value), and adds a
  parallel assertion for x-amzn-lambda-context — both call sites now
  exercise strip_forbidden_header_bytes and round-trip through JSON.
@bnusunny bnusunny merged commit c870b8c into main May 28, 2026
7 checks passed
@bnusunny bnusunny deleted the fix/issue-732-sanitize-control-bytes-header branch May 28, 2026 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

InvalidHeaderValue error on valid HTTP request

2 participants