Repository navigation
Conversation
HttpRequest::ToCrtHttpRequest() was constructing an absolute-form request-target (e.g., "PUT http://host/path HTTP/1.1") for every request. This violates RFC 9112 §3.2.1, which requires origin-form (path + query only) when a client connects directly to an origin server. aws-c-http already handles proxy rewriting via aws_http_rewrite_uri_for_proxy_request, converting to absolute-form only when necessary. By passing origin-form here, we prevent security tools like CrowdSec's http-open-proxy scenario from flagging legitimate S3-compatible storage requests as proxy abuse. Fixes aws#3956
- Remove .changelog file (upstream has no such directory) - Move ToCrtHttpRequestOriginForm test outside DISABLE_DNS_REQUIRED_TESTS guard as it requires no network access
| // Set path to origin-form (path + query only) per RFC 9112 §3.2.1. | ||
| // aws-c-http converts to absolute-form only when sending through a | ||
| // forward proxy via aws_http_rewrite_uri_for_proxy_request. | ||
| ss << (uri.GetPath().empty() ? "/" : uri.GetURLEncodedPath()) |
There was a problem hiding this comment.
GetPath() adds a / before every segment, and adds one more when there are no segments. Every possible result therefore starts with / and the result will never be empty. This can be simplified to ss << uri.GetURLEncodedPath() << uri.GetQueryString();
| // Root path should be "/" | ||
| EXPECT_EQ("/", path); | ||
| EXPECT_FALSE(path.find("http://") == 0); | ||
| } |
There was a problem hiding this comment.
Could you add cases for the following paths whose behavior changes?
- Root path with a query: https://host/?list-type=2 → /?list-type=2. The old code produced https://host?list-type=2.
- Trailing slash: https://host/bucket/prefix/ → /bucket/prefix/.
- Characters that need encoding in the key, e.g. a:b c+d → /bucket/a%3Ab%20c%2Bd.
- Aws::Http::SetPreservePathSeparators(true) with a key that starts with /, which should produce //key. Reset it to false afterwards so it doesn't leak into other tests.
also, each case should be a separate TEST_F instead of scoped blocks in one test, so a failure points at the specific case
| // Root path should be "/" | ||
| EXPECT_EQ("/", path); | ||
| EXPECT_FALSE(path.find("http://") == 0); | ||
| } |
There was a problem hiding this comment.
Can you move this to its own file, e.g. http/HttpRequestTest.cpp. HttpClientTest.cpp is about the HTTP clients and is almost entirely behind DISABLE_DNS_REQUIRED_TESTS, which is why the includes end up repeated mid-file here. http/*.cpp is globbed, so no CMake change is needed.
Use GetURLEncodedPath() plus the query string. That path always starts with '/', so the empty-path fallback was unnecessary. Move the ToCrtHttpRequest cases into http/HttpRequestTest.cpp and give each one its own test, including root-plus-query, a trailing slash, reserved characters, and a preserved leading slash.
Put the cases in the repo clang-format style and leave HttpClientTest.cpp unchanged from main.
|
Thanks for the review. Updated:
|
Issue #, if available:
Fixes #3956
Description of changes:
This PR fixes
S3CrtClientto send origin-form request-targets (e.g.,PUT /bucket/key HTTP/1.1) instead of absolute-form (e.g.,PUT http://host/bucket/key HTTP/1.1) when connecting directly to origin servers.Problem:
HttpRequest::ToCrtHttpRequest()was constructing absolute-form request-targets for all requests by prepending the scheme, authority, and port to the path. This violates RFC 9112 §3.2.1, which requires origin-form (path + query only) for direct connections to origin servers. While S3 and most S3-compatible servers accept absolute-form, security tools like CrowdSec'shttp-open-proxyscenario treat it as open-proxy probing, causing IP bans after a single failed request.Solution:
Modified
ToCrtHttpRequest()insrc/aws-cpp-sdk-core/source/http/HttpRequest.cppto set only the path and query string, removing the scheme, authority, and port components.Proxy behavior is preserved:
The CRT HTTP layer (
aws-c-http) handles proxy rewriting viaaws_http_rewrite_uri_for_proxy_request(file:crt/aws-crt-cpp/crt/aws-c-http/source/proxy_connection.c, lines 931-1000). This function:s_proxy_http_request_transformat line 1010)This is per RFC 7230 §5.3.2, which requires absolute-form only for requests through forward proxies. Direct connections use origin-form.
Signing is not affected:
The CRT signers (SigV4/SigV4a via
ToCrtHttpRequest) compute signatures over the canonical URI, which should be just the path component. The signing configuration includes the region and service name separately (seeAWSAuthV4Signer.cpplines 95-98), and the Host header is already set correctly. All 1088 core tests pass with this change.Testing:
Added unit test
HttpRequestConversionTest.ToCrtHttpRequestOriginFormthat verifies:Test is placed outside
DISABLE_DNS_REQUIRED_TESTSguard as it requires no network access.Test output before fix (showing absolute-form bug):
Test output after fix (origin-form, all tests pass):
Full test suite: 1088 tests passed.
Check all that applies:
Check which platforms you have built SDK on to verify the correctness of this PR.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Generated with AI assistance and reviewed by hippi345.