Skip to content

Commit d94d178

Browse files
authored
auth: exclude additional hop-by-hop headers from SigV4 signing (boto#3643)
1 parent 29eb9dd commit d94d178

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"type": "enhancement",
3+
"category": "auth",
4+
"description": "Exclude additional hop-by-hop headers from SigV4 signing to prevent signature mismatches when intermediaries mutate transport headers (connection, keep-alive, proxy-authenticate, proxy-authorization, TE, trailer, upgrade)."
5+
}

botocore/auth.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,15 @@
6262
ISO8601 = '%Y-%m-%dT%H:%M:%SZ'
6363
SIGV4_TIMESTAMP = '%Y%m%dT%H%M%SZ'
6464
SIGNED_HEADERS_BLACKLIST = [
65+
'connection',
6566
'expect',
67+
'keep-alive',
68+
'proxy-authenticate',
69+
'proxy-authorization',
70+
'te',
71+
'trailer',
6672
'transfer-encoding',
73+
'upgrade',
6774
'user-agent',
6875
'x-amzn-trace-id',
6976
]

tests/unit/auth/test_signers.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,12 @@ def _test_blocklist_header(self, header, value):
386386
)
387387
auth = self.AuthClass(credentials, 's3', 'us-east-1')
388388
auth.add_auth(request)
389-
self.assertNotIn(header, request.headers['Authorization'])
389+
signed_headers = (
390+
request.headers['Authorization']
391+
.split('SignedHeaders=', 1)[1]
392+
.split(',', 1)[0]
393+
)
394+
self.assertNotIn(header.lower(), signed_headers.split(';'))
390395

391396
def test_blocklist_expect_headers(self):
392397
self._test_blocklist_header('expect', '100-continue')
@@ -402,6 +407,31 @@ def test_blocklist_user_agent_header(self):
402407
def test_blocklist_transfer_encoding_header(self):
403408
self._test_blocklist_header('transfer-encoding', 'chunked')
404409

410+
def test_blocklist_connection_header(self):
411+
self._test_blocklist_header('connection', 'keep-alive')
412+
413+
def test_blocklist_keep_alive_header(self):
414+
self._test_blocklist_header('keep-alive', 'timeout=5')
415+
416+
def test_blocklist_proxy_authenticate_header(self):
417+
self._test_blocklist_header(
418+
'proxy-authenticate', 'Basic realm="proxy.example.com"'
419+
)
420+
421+
def test_blocklist_proxy_authorization_header(self):
422+
self._test_blocklist_header(
423+
'proxy-authorization', 'Basic YWxhZGRpbjpvcGVuc2VzYW1l'
424+
)
425+
426+
def test_blocklist_te_header(self):
427+
self._test_blocklist_header('te', 'trailers')
428+
429+
def test_blocklist_trailer_header(self):
430+
self._test_blocklist_header('trailer', 'x-amz-checksum-sha256')
431+
432+
def test_blocklist_upgrade_header(self):
433+
self._test_blocklist_header('upgrade', 'websocket')
434+
405435
def test_uses_sha256_if_config_value_is_true(self):
406436
self.client_config.s3['payload_signing_enabled'] = True
407437
self.auth.add_auth(self.request)

0 commit comments

Comments
 (0)