Command-line tools
AWS CLI SSL validation failed for https://: causes and fixes
SSL validation failed for https://SSL validation failed for https://... means the AWS CLI could not verify the TLS certificate of the AWS endpoint it called. The text after the URL, usually [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate, is the real reason. In most offices a TLS-inspecting proxy is the cause; give the CLI its root with ca_bundle.
What the error means
The text after the endpoint URL is the Python ssl error that caused the failure. botocore defines SSLError with the format SSL validation failed for {endpoint_url} {error}. The CLI prints the endpoint it tried and the underlying Python ssl error:
SSL validation failed for https://ec2.us-east-1.amazonaws.com/ [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1006)
AWS's own troubleshooting guide lists these shapes and causes:
[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: the CLI does not trust your proxy's certificate, typically a proxy whose certificate is issued by your company's CA.[Errno 2] No such file or directory: the configured CA bundle path is wrong.[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled: a TLS stack mismatch, covered in UNSAFE_LEGACY_RENEGOTIATION_DISABLED.
Because the TLS check happens before anything is signed, credentials are not involved.
Causes, most common first
1. A proxy or security product re-signs HTTPS
Secure web gateways and antivirus HTTPS scanning replace AWS's certificate with one issued by their own root. Browsers trust it through the OS store; the CLI does not.
- Confirm:
openssl s_client -connect sts.amazonaws.com:443 -servername sts.amazonaws.com </dev/null 2>/dev/null | openssl x509 -noout -issuer
An issuer naming your company or a security vendor instead of Amazon confirms it. See corporate SSL inspection.
- Fix: export the proxy root in PEM format and set
ca_bundle(below).
2. ca_bundle or AWS_CA_BUNDLE points to a missing or wrong file
A typo, a relative path, a file that only contains the company root when you also need public roots, or a DER file instead of PEM.
- Confirm:
aws configure get ca_bundle,echo $AWS_CA_BUNDLE, thenopenssl x509 -in "$AWS_CA_BUNDLE" -noout -subjectto see that the file is readable PEM. - Fix: use an absolute path to a PEM bundle. If the proxy re-signs all traffic, its root alone is enough; if only some traffic is inspected, build a bundle that contains public roots plus the company root.
3. The host name does not match: dotted S3 buckets or custom endpoints
S3 virtual-hosted-style requests put the bucket in the host name. AWS documents that bucket names with periods cannot use virtual-host-style addressing over HTTPS unless you perform your own certificate validation. A custom --endpoint-url with an IP address or alias causes the same Hostname mismatch.
- Fix:
aws configure set default.s3.addressing_style path, or use the endpoint's real host name.
4. A private S3-compatible or test endpoint
MinIO, Ceph, LocalStack and internal gateways often use a self-signed or private-CA certificate. Point ca_bundle at that CA.
5. Old or unusual TLS on the path
Legacy proxies can trigger renegotiation or protocol errors under OpenSSL 3. See the linked pages for the exact reason code.
Fix commands by platform
Most platforms need the same fix: save the inspecting proxy's root as a PEM file and point ca_bundle or AWS_CA_BUNDLE at it. Dotted bucket names need path-style addressing instead.
Linux and macOS:
aws configure set ca_bundle /etc/ssl/certs/company-bundle.pem # saved in ~/.aws/config
export AWS_CA_BUNDLE=/etc/ssl/certs/company-bundle.pem # per shell / CI job
aws s3 ls --ca-bundle /etc/ssl/certs/company-bundle.pem # one command, highest precedence
Windows (PowerShell): export the root from certmgr.msc as "Base-64 encoded X.509 (.CER)" and save it as company-root.pem, then:
aws configure set ca_bundle C:\certs\company-root.pem
$env:AWS_CA_BUNDLE = "C:\certs\company-root.pem"
boto3 in Python code:
import boto3
s3 = boto3.client("s3", verify="/etc/ssl/certs/company-bundle.pem")
Dotted bucket names:
aws configure set default.s3.addressing_style path
Don't disable certificate verification
Disabling verification hides the error and exposes AWS credentials to interception. --no-verify-ssl (or verify=False in boto3) silences the error. AWS's documentation is explicit that this option is not best practice: traffic between your client and AWS is no longer secured and is vulnerable to man-in-the-middle exploits, and certificate problems should be resolved instead. On a network path that someone can tamper with, that exposes temporary credentials, session tokens and data in S3.
The safer alternatives are the documented ones: ca_bundle, AWS_CA_BUNDLE or --ca-bundle with the right PEM file, path-style addressing for dotted buckets, the endpoint's real host name, and fixing proxies that use outdated TLS.
Verify the fix
aws sts get-caller-identity
aws s3 ls --debug 2>&1 | grep -iE "ssl|certificate" | head
get-caller-identity should return your account and ARN, which proves both TLS and credentials work. The debug output should not contain SSL errors. If you manage the endpoint, check its chain in the SSL checker; for background on why one missing root breaks the CLI but not the browser, see certificate chains explained.
FAQ
Which setting should I use for a custom CA bundle?
Use the AWS-specific ones: the ca_bundle profile setting for a machine, the AWS_CA_BUNDLE environment variable for a shell or CI job, and the --ca-bundle option for a single command. They are the documented way to tell botocore which CA bundle to use, and --ca-bundle overrides the other two.
Why does it fail only for one S3 bucket?
Check the bucket name for periods. With virtual-hosted-style requests the bucket name becomes part of the host name, and a name like my.bucket.example produces a host that the S3 wildcard certificate cannot match. AWS recommends avoiding periods in bucket names; set the CLI to path-style addressing for such buckets.
The error appears with a custom --endpoint-url. What should I check?
S3-compatible storage, VPC endpoints and LocalStack-style test servers often use private or self-signed certificates, or certificates for a different name than the one in --endpoint-url. Point ca_bundle at the CA that issued the endpoint's certificate and use the exact host name on that certificate.
Is this related to my AWS credentials?
No. The TLS check happens before any request is signed or authenticated. Credential problems produce errors such as InvalidAccessKeyId or SignatureDoesNotMatch after a successful TLS connection.
Sources
- AWS CLI User Guide: Troubleshooting errors (SSL certificate errors)
- AWS CLI User Guide: Command line options (--ca-bundle, --no-verify-ssl)
- AWS CLI User Guide: Configuration file settings (ca_bundle)
- AWS CLI: S3 configuration (addressing_style)
- Amazon S3 User Guide: General purpose bucket naming rules
- botocore source: exceptions.py (SSLError)