# PYTHON-LANG-SEC-054: Insecure HTTP Connection via http.client

> **Severity:** MEDIUM | **CWE:** CWE-319 | **OWASP:** A02:2021

- **Language:** Python
- **Category:** Python Core
- **URL:** https://codepathfinder.dev/registry/python/lang/PYTHON-LANG-SEC-054
- **Detection:** `pathfinder scan --ruleset python/PYTHON-LANG-SEC-054 --project .`

## Description

http.client.HTTPConnection creates an unencrypted HTTP connection that transmits all
data in plaintext. Any data sent over this connection including authentication tokens,
session cookies, API keys, user data, and sensitive parameters can be intercepted by
anyone on the network path between the client and server.

HTTP (without TLS) should not be used for any endpoint that transmits sensitive data.
HTTPSConnection (http.client.HTTPSConnection) uses TLS to encrypt the connection,
protecting data confidentiality and authenticating the server.

HTTPConnection is appropriate for: internal health check endpoints on localhost,
connections to infrastructure components on a private, isolated network where TLS
termination occurs at a load balancer, and specific protocol requirements. For all
other use cases, HTTPSConnection or the requests library with HTTPS URLs should be used.


## Vulnerable Code

```python
import ssl
import http.client
import requests as http_requests

conn = http.client.HTTPConnection("example.com")
```

## Secure Code

```python
import http.client
import ssl

# INSECURE: Plain HTTP connection
# conn = http.client.HTTPConnection("api.example.com")
# conn.request("GET", "/sensitive-data", headers={"Authorization": "Bearer token"})

# SECURE: HTTPS connection with default SSL context
def make_https_request(host: str, path: str, token: str) -> str:
    ctx = ssl.create_default_context()
    conn = http.client.HTTPSConnection(host, context=ctx)
    conn.request("GET", path, headers={"Authorization": f"Bearer {token}"})
    response = conn.getresponse()
    return response.read().decode()

# PREFERRED: Use the requests library for a simpler, safer API
import requests

def make_api_request(url: str, token: str) -> dict:
    response = requests.get(
        url,
        headers={"Authorization": f"Bearer {token}"},
        timeout=30,
    )
    response.raise_for_status()
    return response.json()

```

## Detection Rule (Python SDK)

```python
from rules.python_decorators import python_rule
from codepathfinder import calls, QueryType

class HttplibModule(QueryType):
    fqns = ["http.client"]


@python_rule(
    id="PYTHON-LANG-SEC-054",
    name="Insecure HTTP Connection",
    severity="MEDIUM",
    category="lang",
    cwe="CWE-319",
    tags="python,http,plaintext,insecure-transport,CWE-319",
    message="HTTPConnection used instead of HTTPSConnection. Use HTTPS for sensitive communications.",
    owasp="A02:2021",
)
def detect_http_connection():
    """Detects http.client.HTTPConnection usage."""
    return HttplibModule.method("HTTPConnection")
```

## How to Fix

- Replace http.client.HTTPConnection with http.client.HTTPSConnection for all external service calls.
- Use the requests library with https:// URLs as a higher-level, safer alternative to http.client.
- For internal service-to-service communication in containerized environments, use HTTPS even on private networks to protect against internal threats and lateral movement.
- If HTTP must be used for specific infrastructure reasons (health checks, load balancer endpoints), ensure sensitive data is never transmitted over these endpoints.
- Configure HSTS (HTTP Strict Transport Security) on servers to prevent clients from accidentally connecting over HTTP.

## Security Implications

- **Credential Interception:** Authentication headers (Basic auth, Bearer tokens, API keys), form credentials, and
session cookies transmitted over HTTP are visible in plaintext to any observer on
the network, including the ISP, corporate network monitoring, and MITM attackers.

- **Session Hijacking:** HTTP cookies visible on the network allow session hijacking: an attacker who captures
the session token can use it to authenticate as the victim without knowing the password.

- **Data Integrity Failure:** HTTP provides no integrity protection. An attacker on the network path can inject,
modify, or suppress HTTP traffic. Responses can be modified to serve malicious content,
and requests can be altered to change transaction parameters.

- **Compliance Violations:** Transmitting cardholder data (PCI DSS), health information (HIPAA), or personal data
(GDPR) over unencrypted HTTP violates regulatory requirements and may result in
significant fines and mandatory breach notifications.


## FAQ

**Q: Is HTTP acceptable for internal microservice communication?**

HTTP without TLS is risky even on internal networks. Compromised internal services,
lateral movement attacks, and network sniffing on internal subnets can all intercept
plaintext HTTP traffic. Use HTTPS with service mesh mTLS (Istio, Linkerd) or at
minimum HTTPS with internal CA certificates for service-to-service communication.


**Q: What about connecting to a local service for health checks?**

Health check endpoints on localhost (127.0.0.1) that do not transmit sensitive data
are generally acceptable over HTTP. If the health check endpoint returns information
about internal service configuration or secrets, use HTTPS even for localhost
connections.


**Q: Is http.client.HTTPConnection safer than requests with an http:// URL?**

No, both transmit data in plaintext over TCP without TLS. The security risk is
identical. The requests library is generally preferred for its simpler API, better
defaults, and built-in support for session management, retries, and certificate
verification.


**Q: How do I add a custom SSL context to HTTPSConnection?**

Pass the context parameter: http.client.HTTPSConnection(host, context=ssl_ctx).
Use ssl.create_default_context() for the context object unless you have specific
requirements. This ensures certificate verification and hostname checking are enabled.


**Q: What port does HTTPSConnection use by default?**

http.client.HTTPSConnection defaults to port 443 (HTTPS). http.client.HTTPConnection
defaults to port 80 (HTTP). Specify a custom port as the second argument if needed:
HTTPSConnection("api.example.com", 8443).


**Q: Does this rule catch http.client.HTTPConnection used through urllib?**

urllib.request.urlopen() on HTTP URLs uses http.client.HTTPConnection internally.
PYTHON-LANG-SEC-061 covers urllib.request.urlopen() with HTTP URLs specifically.
This rule targets direct http.client.HTTPConnection() constructor calls.


## References

- [CWE-319: Cleartext Transmission of Sensitive Information](https://cwe.mitre.org/data/definitions/319.html)
- [Python docs: http.client.HTTPConnection](https://docs.python.org/3/library/http.client.html#http.client.HTTPConnection)
- [Python docs: http.client.HTTPSConnection](https://docs.python.org/3/library/http.client.html#http.client.HTTPSConnection)
- [OWASP TLS Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Transport_Layer_Security_Cheat_Sheet.html)
- [OWASP Top 10 A02:2021 Cryptographic Failures](https://owasp.org/Top10/A02_2021-Cryptographic_Failures/)

---

Source: https://codepathfinder.dev/registry/python/lang/PYTHON-LANG-SEC-054
Code Pathfinder — Open source, type-aware SAST with cross-file dataflow analysis
