https://github.com/zaczero/httpx-secure
Drop-in SSRF protection for httpx
https://github.com/zaczero/httpx-secure
dns-cache httpx security server-side-request-forgery ssrf web-security
Last synced: 4 months ago
JSON representation
Drop-in SSRF protection for httpx
- Host: GitHub
- URL: https://github.com/zaczero/httpx-secure
- Owner: Zaczero
- License: 0bsd
- Created: 2025-08-15T15:51:32.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2025-08-16T11:09:16.000Z (5 months ago)
- Last Synced: 2025-09-05T14:00:08.442Z (4 months ago)
- Topics: dns-cache, httpx, security, server-side-request-forgery, ssrf, web-security
- Language: Python
- Homepage: https://pypi.org/p/httpx-secure
- Size: 28.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# httpx-secure
[](https://pypi.org/p/httpx-secure)
[](https://liberapay.com/Zaczero/)
[](https://github.com/sponsors/Zaczero)
Drop-in SSRF protection for httpx.
## Why Use This?
- **SSRF Protection**: Block requests to private/internal IP addresses
- **Custom Validation**: Extend with your own validation logic
- **Minimal Overhead**: Efficient implementation with built-in DNS caching
- **Broad Python Support**: Compatible with Python 3.9+
- [**Semantic Versioning**](https://semver.org): Predictable, reliable updates
- [**Zero-Clause BSD**](https://choosealicense.com/licenses/0bsd/): Public domain, use freely anywhere
## Installation
```bash
pip install httpx-secure
```
## Quick Start
```python
import httpx
from httpx_secure import httpx_ssrf_protection
client = httpx_ssrf_protection(
httpx.AsyncClient(),
dns_cache_size=1000, # Cache up to 1000 DNS resolutions
dns_cache_ttl=600, # Cache for 10 minutes
)
await client.get("https://public.domain") # Allowed
await client.get("https://private.domain") # Blocked
```
## Custom Validation
For example, implement a simple domain whitelist to restrict requests to specific hosts:
```python
import httpx
from httpx_secure import httpx_ssrf_protection
from ipaddress import IPv4Address, IPv6Address
def custom_validator(
hostname: str,
ip: IPv4Address | IPv6Address,
port: int
) -> bool:
return hostname in {
"whitelisted.domain",
"webhook.partner.com",
}
client = httpx_ssrf_protection(
httpx.AsyncClient(),
custom_validator=custom_validator,
)
await client.get("https://whitelisted.domain") # Allowed
await client.get("https://unknown.domain") # Blocked
```
## How It Works
1. **Cache Lookup**: First checks if the host has been recently validated and cached
2. **DNS Resolution**: If not cached, resolves the hostname to an IP address
3. **Validation**: Verifies the IP is globally routable, blocking private/internal addresses
4. **Custom Validation**: If provided, your custom validator is called for additional checks
5. **Request Modification**: Rewrites the request to use the validated IP directly
The DNS cache significantly reduces latency for repeated requests, while per-host locking ensures efficient concurrent resolution of parallel requests.
> [!TIP]
> The SSRF protection applies to all HTTP methods (GET, POST, PUT, DELETE, etc.) and automatically validates redirects to prevent SSRF attacks through redirect chains.