Summary
The network allowlist checks URL hostnames as literal strings against the allowlist, then relies on reqwest to resolve DNS and make the connection. An attacker who controls a domain's DNS records can point an allowed hostname at internal services (169.254.169.254, 127.0.0.1, internal network IPs) between the allowlist check and the actual connection.
While the allowlist documentation notes this limitation (TM-NET-002), the current mitigation is incomplete: it prevents DNS rebinding where the hostname changes between checks, but does NOT prevent the case where an explicitly allowed hostname resolves to an internal IP.
Threat category: TM-NET (Network Security) — extends TM-NET-002, TM-NET-004
Severity: Medium
Component: `crates/bashkit/src/network/allowlist.rs`, `crates/bashkit/src/network/client.rs`
Root Cause
// allowlist.rs - checks hostname string only
fn matches_pattern(&self, url: &Url, pattern: &str) -> bool {
// Check host - string comparison only
match (url.host_str(), pattern_url.host_str()) {
(Some(url_host), Some(pattern_host)) => {
if url_host != pattern_host { return false; }
}
_ => return false,
}
// ... no IP resolution check
}
The client then makes the request, and reqwest resolves the hostname to an IP. If the allowed domain `api.attacker.com` resolves to `169.254.169.254` (AWS metadata), the request proceeds to the metadata service.
Steps to Reproduce
// Attacker controls api.attacker.com DNS
// DNS: api.attacker.com -> 169.254.169.254
let allowlist = NetworkAllowlist::new()
.allow("https://api.attacker.com");
// This passes the allowlist check (hostname matches)
// but connects to AWS metadata service
let client = HttpClient::new(allowlist);
client.request(Method::Get,
"https://api.attacker.com/latest/meta-data/iam/security-credentials/",
None, &[]).await;
// Returns AWS credentials!
Impact
- Cloud metadata theft: Access to AWS/GCP/Azure instance metadata (IAM credentials, tokens)
- Internal service access: Reach internal APIs, databases, admin panels
- Network scanning: Map internal infrastructure by trying different ports
Acceptance Criteria
Note
The existing threat model acknowledges TM-NET-002 (DNS rebinding) and TM-NET-004 (IP-based bypass). This issue proposes a concrete implementation to close the gap between the threat model and the actual code.
Summary
The network allowlist checks URL hostnames as literal strings against the allowlist, then relies on reqwest to resolve DNS and make the connection. An attacker who controls a domain's DNS records can point an allowed hostname at internal services (169.254.169.254, 127.0.0.1, internal network IPs) between the allowlist check and the actual connection.
While the allowlist documentation notes this limitation (TM-NET-002), the current mitigation is incomplete: it prevents DNS rebinding where the hostname changes between checks, but does NOT prevent the case where an explicitly allowed hostname resolves to an internal IP.
Threat category: TM-NET (Network Security) — extends TM-NET-002, TM-NET-004
Severity: Medium
Component: `crates/bashkit/src/network/allowlist.rs`, `crates/bashkit/src/network/client.rs`
Root Cause
The client then makes the request, and reqwest resolves the hostname to an IP. If the allowed domain `api.attacker.com` resolves to `169.254.169.254` (AWS metadata), the request proceeds to the metadata service.
Steps to Reproduce
Impact
Acceptance Criteria
Note
The existing threat model acknowledges TM-NET-002 (DNS rebinding) and TM-NET-004 (IP-based bypass). This issue proposes a concrete implementation to close the gap between the threat model and the actual code.