# AWS CLI SSL validation failed for https://: causes and fixes

> botocore prints SSL validation failed for <endpoint> when the TLS check fails. Fix it with ca_bundle, the right endpoint, or path-style S3.

Source: https://ssl.sh/errors/aws-cli-ssl-validation-failed/
Last updated: 2026-11-10

**`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:

```text
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](https://ssl.sh/errors/python-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:**

```bash
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](https://ssl.sh/errors/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`, then `openssl x509 -in "$AWS_CA_BUNDLE" -noout -subject` to 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:**

```bash
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:

```powershell
aws configure set ca_bundle C:\certs\company-root.pem
$env:AWS_CA_BUNDLE = "C:\certs\company-root.pem"
```

**boto3 in Python code:**

```python
import boto3
s3 = boto3.client("s3", verify="/etc/ssl/certs/company-bundle.pem")
```

**Dotted bucket names:**

```bash
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

```bash
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](https://ssl.sh/tools/ssl-checker/); for background on why one missing root breaks the CLI but not the browser, see [certificate chains explained](https://ssl.sh/learn/certificate-chains/).
