Skip to content

Commit 9f44cdb

Browse files
authored
fix: ignore hop-by-hop headers when signing requests (#1227)
1 parent 03badf9 commit 9f44cdb

File tree

5 files changed

+36
-13
lines changed

5 files changed

+36
-13
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"id": "b0646077-397d-48a8-94f2-ea2db40b1dea",
3+
"type": "bugfix",
4+
"description": "Ignore hop-by-hop headers when signing requests"
5+
}

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ okio-version = "3.9.1"
1313
otel-version = "1.45.0"
1414
slf4j-version = "2.0.16"
1515
slf4j-v1x-version = "1.7.36"
16-
crt-kotlin-version = "0.9.0"
16+
crt-kotlin-version = "0.9.1"
1717
micrometer-version = "1.14.2"
1818
binary-compatibility-validator-version = "0.16.3"
1919

runtime/auth/aws-signing-default/common/src/aws/smithy/kotlin/runtime/auth/awssigning/Canonicalizer.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,27 @@ internal interface Canonicalizer {
5858
): CanonicalRequest
5959
}
6060

61-
// Taken from https://github.com/awslabs/aws-c-auth/blob/dd505b55fd46222834f35c6e54165d8cbebbfaaa/source/aws_signing.c#L118-L156
6261
private val skipHeaders = setOf(
63-
"connection",
6462
"expect", // https://github.com/awslabs/aws-sdk-kotlin/issues/862
63+
64+
// Taken from https://github.com/awslabs/aws-c-auth/blob/274a1d21330731cc51bb742794adc70ada5f4380/source/aws_signing.c#L121-L164
6565
"sec-websocket-key",
6666
"sec-websocket-protocol",
6767
"sec-websocket-version",
68-
"upgrade",
6968
"user-agent",
7069
"x-amzn-trace-id",
70+
71+
// Taken from https://datatracker.ietf.org/doc/html/rfc2616#section-13.5.1. These are "hop-by-hop" headers which may
72+
// be modified/removed by intervening proxies or caches. These are unsafe to sign because if they change they render
73+
// the signature invalid.
74+
"connection",
75+
"keep-alive",
76+
"proxy-authenticate",
77+
"proxy-authorization",
78+
"te",
79+
"trailers",
80+
"transfer-encoding",
81+
"upgrade",
7182
)
7283

7384
internal class DefaultCanonicalizer(private val sha256Supplier: HashSupplier = ::Sha256) : Canonicalizer {

runtime/auth/aws-signing-default/common/test/aws/smithy/kotlin/runtime/auth/awssigning/DefaultCanonicalizerTest.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ package aws.smithy.kotlin.runtime.auth.awssigning
66

77
import aws.smithy.kotlin.runtime.auth.awscredentials.Credentials
88
import aws.smithy.kotlin.runtime.auth.awssigning.tests.DEFAULT_TEST_CREDENTIALS
9-
import aws.smithy.kotlin.runtime.http.*
10-
import aws.smithy.kotlin.runtime.http.request.*
9+
import aws.smithy.kotlin.runtime.http.Headers
10+
import aws.smithy.kotlin.runtime.http.HttpBody
11+
import aws.smithy.kotlin.runtime.http.HttpMethod
12+
import aws.smithy.kotlin.runtime.http.request.HttpRequest
13+
import aws.smithy.kotlin.runtime.http.request.headers
14+
import aws.smithy.kotlin.runtime.http.request.url
1115
import aws.smithy.kotlin.runtime.net.Host
1216
import aws.smithy.kotlin.runtime.net.url.Url
1317
import aws.smithy.kotlin.runtime.time.Instant
@@ -136,6 +140,7 @@ class DefaultCanonicalizerTest {
136140
// These should not be signed
137141
set("Expect", "100-continue")
138142
set("X-Amzn-Trace-Id", "qux")
143+
set("Transfer-Encoding", "chunked")
139144
}
140145
body = HttpBody.Empty
141146
}

runtime/auth/http-auth-aws/common/test/aws/smithy/kotlin/runtime/http/auth/AwsHttpSignerTestBase.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ import aws.smithy.kotlin.runtime.auth.awssigning.DefaultAwsSigner
1212
import aws.smithy.kotlin.runtime.auth.awssigning.internal.AWS_CHUNKED_THRESHOLD
1313
import aws.smithy.kotlin.runtime.collections.Attributes
1414
import aws.smithy.kotlin.runtime.collections.get
15-
import aws.smithy.kotlin.runtime.http.*
15+
import aws.smithy.kotlin.runtime.http.HttpBody
16+
import aws.smithy.kotlin.runtime.http.HttpMethod
17+
import aws.smithy.kotlin.runtime.http.SdkHttpClient
1618
import aws.smithy.kotlin.runtime.http.operation.*
1719
import aws.smithy.kotlin.runtime.http.request.HttpRequest
1820
import aws.smithy.kotlin.runtime.http.request.HttpRequestBuilder
@@ -149,8 +151,8 @@ public abstract class AwsHttpSignerTestBase(
149151
val op = buildOperation(streaming = true, replayable = false, requestBody = "a".repeat(AWS_CHUNKED_THRESHOLD + 1))
150152
val expectedDate = "20201016T195600Z"
151153
val expectedSig = "AWS4-HMAC-SHA256 Credential=AKID/20201016/us-east-1/demo/aws4_request, " +
152-
"SignedHeaders=content-encoding;host;transfer-encoding;x-amz-archive-description;x-amz-date;x-amz-decoded-content-length;x-amz-security-token, " +
153-
"Signature=ac341b9b248a0b23d2fcd9f7e805f4eb0b8a1b789bb23a8ec6adc6c48dd084ad"
154+
"SignedHeaders=content-encoding;host;x-amz-archive-description;x-amz-date;x-amz-decoded-content-length;x-amz-security-token, " +
155+
"Signature=ef06c95647c4d2daa6c89ac90274f1c780777cba8eaab772df6d8009def3eb8f"
154156

155157
val signed = getSignedRequest(op)
156158
assertEquals(expectedDate, signed.headers["X-Amz-Date"])
@@ -162,8 +164,8 @@ public abstract class AwsHttpSignerTestBase(
162164
val op = buildOperation(streaming = true, replayable = true, requestBody = "a".repeat(AWS_CHUNKED_THRESHOLD + 1))
163165
val expectedDate = "20201016T195600Z"
164166
val expectedSig = "AWS4-HMAC-SHA256 Credential=AKID/20201016/us-east-1/demo/aws4_request, " +
165-
"SignedHeaders=content-encoding;host;transfer-encoding;x-amz-archive-description;x-amz-date;x-amz-decoded-content-length;x-amz-security-token, " +
166-
"Signature=ac341b9b248a0b23d2fcd9f7e805f4eb0b8a1b789bb23a8ec6adc6c48dd084ad"
167+
"SignedHeaders=content-encoding;host;x-amz-archive-description;x-amz-date;x-amz-decoded-content-length;x-amz-security-token, " +
168+
"Signature=ef06c95647c4d2daa6c89ac90274f1c780777cba8eaab772df6d8009def3eb8f"
167169

168170
val signed = getSignedRequest(op)
169171
assertEquals(expectedDate, signed.headers["X-Amz-Date"])
@@ -176,8 +178,8 @@ public abstract class AwsHttpSignerTestBase(
176178
val expectedDate = "20201016T195600Z"
177179
// should have same signature as testSignAwsChunkedStreamNonReplayable(), except for the hash, since the body is different
178180
val expectedSig = "AWS4-HMAC-SHA256 Credential=AKID/20201016/us-east-1/demo/aws4_request, " +
179-
"SignedHeaders=content-encoding;host;transfer-encoding;x-amz-archive-description;x-amz-date;x-amz-decoded-content-length;x-amz-security-token, " +
180-
"Signature=3f0277123c9ed8a8858f793886a0ac0fcb457bc54401ffc22d470f373397cff0"
181+
"SignedHeaders=content-encoding;host;x-amz-archive-description;x-amz-date;x-amz-decoded-content-length;x-amz-security-token, " +
182+
"Signature=a902702b57057a864bf41cc22ee846a1b7bd047e22784367ec6a459f6791330e"
181183

182184
val signed = getSignedRequest(op)
183185
assertEquals(expectedDate, signed.headers["X-Amz-Date"])

0 commit comments

Comments
 (0)