<div align="center">
# AntiSSRF-rs
[](https://crates.io/crates/antissrf)
[](https://docs.rs/antissrf)
[](LICENSE)
[](https://blog.rust-lang.org/)
**Rust implementation of [Microsoft AntiSSRF](https://microsoft.github.io/AntiSSRF/) — a security library for preventing Server-Side Request Forgery (SSRF) attacks.**
</div>
---
## Overview
AntiSSRF-rs is a Rust version of Microsoft's AntiSSRF library, designed to prevent **Server-Side Request Forgery (SSRF)** attacks by validating every outbound network request against a configurable security policy. It integrates seamlessly with [`reqwest`](https://docs.rs/reqwest) and [`reqwest-middleware`](https://docs.rs/reqwest-middleware) to provide DNS-level IP blocking, header validation, protocol enforcement, and redirect-chain re-validation.
## Features
| **IP Blocking** | Block internal/sensitive IP addresses (localhost, private networks, cloud metadata services) using CIDR ranges |
| **IPv6 Normalization** | Automatically maps IPv4 to IPv6-mapped addresses (`::ffff:`) for consistent CIDR matching |
| **Header Enforcement** | Require specific headers (e.g., `X-Forwarded-For`) and deny dangerous headers |
| **Protocol Control** | Reject plaintext HTTP to untrusted endpoints |
| **Redirect Validation** | Re-validate every hop in a redirect chain against the same policy |
| **Domain Validation** | Check URLs against trusted domains (with subdomain support) and Azure service endpoints |
| **Immutable Policy** | Policy locks after first use to prevent runtime tampering |
| **Optional Networking** | Core library has zero network dependencies; `reqwest-integration` feature adds HTTP client support |
## Quick Start
#### 1. Add to `Cargo.toml`
```toml
[dependencies]
antissrf = "0.1.1"
```
Or with explicit feature control:
```toml
[dependencies]
# Core only (no HTTP client dependencies)
antissrf = { version = "0.1.1", default-features = false }
# Full reqwest integration (default)
antissrf = { version = "0.1.1", features = ["reqwest-integration"] }
```
#### 2. Basic Policy
```rust
use antissrf::{AntiSSRFPolicy, PolicyConfigOptions};
// Block all known dangerous IPs (IMDS, WireServer, private networks, etc.)
let policy = AntiSSRFPolicy::new(PolicyConfigOptions::ExternalOnlyLatest);
```
#### 3. With reqwest (DNS-level IP validation)
```rust
use antissrf::{AntiSSRFPolicy, PolicyConfigOptions};
use antissrf::network::reqwest_integration::AntiSSRFClientBuilder;
let policy = AntiSSRFPolicy::new(PolicyConfigOptions::ExternalOnlyLatest);
let client = AntiSSRFClientBuilder::new(policy)
.timeout(std::time::Duration::from_secs(30))
.build()
.expect("Client should build");
```
#### 4. With reqwest_middleware (header + protocol validation)
```rust
use antissrf::{AntiSSRFPolicy, PolicyConfigOptions};
use antissrf::network::reqwest_integration::AntiSSRFMiddleware;
use reqwest_middleware::ClientBuilder;
let policy = AntiSSRFPolicy::new(PolicyConfigOptions::ExternalOnlyLatest);
let middleware = AntiSSRFMiddleware::new(policy);
let client = ClientBuilder::new(reqwest::Client::new())
.with(middleware)
.build();
```
#### 5. Fine-Grained Policy Configuration
```rust
use antissrf::{AntiSSRFPolicy, PolicyConfigOptions, AntiSSRFError};
let mut policy = AntiSSRFPolicy::new(PolicyConfigOptions::ExternalOnlyLatest);
// Allowlist takes precedence over denylist
policy.add_allowed_addresses(&["10.0.0.0/24"])?;
// Require specific headers
policy.add_required_headers(&["x-request-id"])?;
// Deny dangerous headers
policy.add_denied_headers(&["x-forwarded-host", "x-http-host-override"])?;
// Block plaintext HTTP
policy.set_allow_plaintext_http(false)?;
// Validate an outgoing request
let mut headers = vec![
("x-request-id".to_string(), "abc123".to_string()),
];
let allowed = policy.validate_request("https:", &mut headers)?;
assert!(allowed);
```
#### 6. Domain Validation
```rust
use antissrf::uri_validator;
// Check if URL is in a trusted domain (supports subdomains)
assert!(uri_validator::in_domain("https://api.example.com/path", &["example.com"]));
// Azure Key Vault domain validation
assert!(uri_validator::in_azure_key_vault_domain("https://myvault.vault.azure.net"));
// Rejects hostnames containing '--' (Azure naming restriction)
assert!(!uri_validator::in_azure_key_vault_domain("https://my--vault.vault.azure.net"));
```
## PolicyConfigOptions
| `None` | No restrictions — allow all requests |
| `InternalOnly` | Block external IPs (deny all unspecified) |
| `ExternalOnlyV1` | Block IMDS + WireServer + special ranges (v1 blocklist) |
| `ExternalOnlyLatest` | Same as V1 — alias for the latest recommended blocklist |
## Modules
| [`error`](https://docs.rs/antissrf/latest/antissrf/error/) | Error types (`AntiSSRFError`) |
| [`cidr`](https://docs.rs/antissrf/latest/antissrf/cidr/) | CIDR block parsing and IP containment |
| [`ip_address_ranges`](https://docs.rs/antissrf/latest/antissrf/ip_address_ranges/) | Predefined special IP ranges (IMDS, WireServer, loopback, etc.) |
| [`domains`](https://docs.rs/antissrf/latest/antissrf/domains/) | Azure service domain lists (Key Vault, Storage) |
| [`uri_validator`](https://docs.rs/antissrf/latest/antissrf/uri_validator/) | URL and domain validation utilities |
| [`policy`](https://docs.rs/antissrf/latest/antissrf/policy/) | Policy configuration and runtime enforcement |
| [`network`](https://docs.rs/antissrf/latest/antissrf/network/) | reqwest integration (resolver + middleware + client builder) |
## Running Tests
```bash
# Core tests (no network dependencies)
cargo test --lib
# With reqwest integration (default features)
cargo test --features reqwest-integration
# All tests with output
cargo test --features reqwest-integration -- --nocapture
# Documentation tests
cargo test --doc
```
## Security Design
- **Evaluation Order**: Allowlist → `deny_all_unspecified_ips` → Denylist. An allowlisted IP is always permitted, even if it also appears in a denylist.
- **IPv6 Normalization**: All IPv4 addresses are mapped to `::ffff:<ipv4>` before CIDR checks. IPv4 `/24` becomes IPv6-mapped `/120` (add 96 to prefix length).
- **Case-Insensitive Headers**: Header names are matched case-insensitively; header values are matched case-sensitively.
- **Edit Lock**: Once a policy is used for validation, it becomes immutable to prevent runtime tampering.
- **Redirect Re-Validation**: Every redirect hop is re-validated against the same policy, preventing open-redirect bypasses.
## License
MIT — See [LICENSE](LICENSE) for details.
## References
- [Microsoft AntiSSRF Documentation](https://microsoft.github.io/AntiSSRF/)
- [OWASP SSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html)
- [CWE-918: Server-Side Request Forgery](https://cwe.mitre.org/data/definitions/918.html)