Introduction

The urllib3.exceptions.InsecureRequestWarning is raised when making HTTPS requests with verify=False, which disables TLS certificate verification. While the warning is helpful during development, it becomes problematic in production and CI pipelines where it floods logs, triggers false-positive security alerts, and can cause CI to fail when warnings are treated as errors. The warning is a security signal -- disabling verification exposes the connection to man-in-the-middle attacks -- but sometimes it is unavoidable when connecting to internal services with self-signed certificates.

Symptoms

Logs flooded with warnings:

bash
/usr/local/lib/python3.11/site-packages/urllib3/connectionpool.py:1099: InsecureRequestWarning:
Unverified HTTPS request is being made to host 'internal-api.company.com'.
Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings
  warnings.warn(

CI pipeline fails with -W error::InsecureRequestWarning:

bash
FAILED tests/test_api.py::test_internal_endpoint - urllib3.exceptions.InsecureRequestWarning: Unverified HTTPS request

Or Sentry captures thousands of warning events:

bash
[InsecureRequestWarning] Unverified HTTPS request is being made to host '10.0.1.50'

Common Causes

  • **verify=False in production code**: Disabling verification to bypass certificate issues rather than fixing them
  • Internal services with self-signed certificates: Services that have not been issued proper CA-signed certificates
  • Test fixtures using HTTP instead of HTTPS: Tests connecting to mock servers without TLS
  • Legacy code not updated: Older code that used verify=False before proper CA infrastructure was in place
  • Warning treated as error in CI: CI configured with PYTHONWARNINGS=error::InsecureRequestWarning
  • Corporate MITM proxy: Proxy intercepts traffic with its own certificate not in the Python trust store

Step-by-Step Fix

Step 1: Fix the root cause - configure certificate verification

Instead of disabling verification, point to the correct CA bundle:

```python import requests

# WRONG - disables verification entirely response = requests.get( "https://internal-api.company.com/data", verify=False, )

# CORRECT - use the internal CA bundle response = requests.get( "https://internal-api.company.com/data", verify="/etc/ssl/certs/company-ca-bundle.pem", ) ```

Step 2: Suppress warnings only when verification is intentionally disabled

If you must disable verification (e.g., for a local development server), suppress the warning cleanly:

```python import urllib3 import warnings

# Suppress only InsecureRequestWarning, keep all other warnings active urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# Or use the warnings module for finer control warnings.filterwarnings( "ignore", category=urllib3.exceptions.InsecureRequestWarning, ) ```

Step 3: Configure verification via environment variable

For consistent behavior across environments:

```python import os import requests

# Use REQUESTS_CA_BUNDLE environment variable # Set in production deployment, not in code ca_bundle = os.environ.get( "REQUESTS_CA_BUNDLE", "/etc/ssl/certs/ca-certificates.crt", )

response = requests.get( "https://internal-api.company.com/data", verify=ca_bundle, ) ```

Set the environment variable in your deployment:

```bash # Systemd service Environment=REQUESTS_CA_BUNDLE=/etc/ssl/certs/company-ca-bundle.pem

# Docker docker run -e REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt myapp

# CI pipeline export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ci-ca-bundle.pem ```

Step 4: Add a pre-commit hook to catch verify=False

bash
#!/bin/bash
# .pre-commit-hooks/check-verify-false.sh
if grep -rn "verify=False" --include="*.py" .; then
    echo "ERROR: Found verify=False in code. Use REQUESTS_CA_BUNDLE instead."
    exit 1
fi

Prevention

  • Never use verify=False in production code -- always configure proper CA bundles
  • Use REQUESTS_CA_BUNDLE environment variable to manage certificate paths per environment
  • Add a CI check that fails on verify=False in committed code
  • Use urllib3.disable_warnings() only in test fixtures, never in application code
  • Monitor logs for InsecureRequestWarning and treat each occurrence as a security ticket
  • Set up certificate rotation automation for internal CAs to prevent expiration-related verify=False workarounds