From 2f35595423a111ac6dda2122f4eed4cc5a8097a9 Mon Sep 17 00:00:00 2001 From: Alessandra Romero Date: Fri, 17 Jul 2026 20:35:10 -0400 Subject: [PATCH] Raise error on empty CA bundle value --- .changes/next-release/bugfix-TLS-36922.json | 5 +++++ s3transfer/crt.py | 11 ++++++++++- tests/unit/test_crt.py | 18 +++++++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 .changes/next-release/bugfix-TLS-36922.json diff --git a/.changes/next-release/bugfix-TLS-36922.json b/.changes/next-release/bugfix-TLS-36922.json new file mode 100644 index 00000000..0a59982c --- /dev/null +++ b/.changes/next-release/bugfix-TLS-36922.json @@ -0,0 +1,5 @@ +{ + "type": "bugfix", + "category": "TLS", + "description": "Return a configuration error when the CA bundle value (ca_bundle, AWS_CA_BUNDLE, REQUESTS_CA_BUNDLE, or verify) resolves to an empty string." +} diff --git a/s3transfer/crt.py b/s3transfer/crt.py index c10f53ac..eac7226b 100644 --- a/s3transfer/crt.py +++ b/s3transfer/crt.py @@ -37,7 +37,7 @@ from botocore import UNSIGNED from botocore.compat import urlsplit from botocore.config import Config -from botocore.exceptions import NoCredentialsError +from botocore.exceptions import InvalidConfigError, NoCredentialsError from botocore.utils import ArnParser, InvalidArnException from s3transfer.constants import FULL_OBJECT_CHECKSUM_ARGS, MB @@ -143,6 +143,15 @@ def create_s3_crt_client( S3RequestTlsMode.ENABLED if use_ssl else S3RequestTlsMode.DISABLED ) if verify is not None: + if isinstance(verify, str) and not verify: + raise InvalidConfigError( + error_msg=( + 'Invalid CA bundle: the configured value (ca_bundle, ' + 'AWS_CA_BUNDLE, REQUESTS_CA_BUNDLE, or verify) resolved ' + 'to an empty string. Provide a valid path to a CA bundle ' + 'file.' + ) + ) tls_ctx_options = TlsContextOptions() if verify: tls_ctx_options.override_default_trust_store_from_path( diff --git a/tests/unit/test_crt.py b/tests/unit/test_crt.py index 7d7aa1b5..2c62baeb 100644 --- a/tests/unit/test_crt.py +++ b/tests/unit/test_crt.py @@ -14,7 +14,11 @@ import pytest from botocore.credentials import Credentials, ReadOnlyCredentials -from botocore.exceptions import ClientError, NoCredentialsError +from botocore.exceptions import ( + ClientError, + InvalidConfigError, + NoCredentialsError, +) from botocore.session import Session from s3transfer.exceptions import TransferNotDoneError @@ -366,3 +370,15 @@ def test_target_throughput( def test_always_enables_s3express(self, mock_s3_crt_client): s3transfer.crt.create_s3_crt_client('us-west-2') assert mock_s3_crt_client.call_args[1]['enable_s3express'] is True + + def test_empty_verify_value_raises(self, mock_s3_crt_client): + with pytest.raises(InvalidConfigError): + s3transfer.crt.create_s3_crt_client('us-west-2', verify='') + + def test_verify_false_disables_verification(self, mock_s3_crt_client): + with ( + mock.patch('s3transfer.crt.TlsContextOptions') as mock_tls_options, + mock.patch('s3transfer.crt.ClientTlsContext'), + ): + s3transfer.crt.create_s3_crt_client('us-west-2', verify=False) + assert mock_tls_options.return_value.verify_peer is False