Sep 5, 2026·6 min read·26 visits
A Time-of-Check to Time-of-Use (TOCTOU) flaw in CodeWhale's DNS validation logic allows unauthenticated attackers to bypass SSRF protections by intentionally failing the initial DNS resolution and resolving to a restricted IP during the subsequent HTTP request.
A critical Server-Side Request Forgery (SSRF) bypass vulnerability exists in CodeWhale before version 0.8.64 (and version 0.8.41 in the 0.8.x branch) due to a Time-of-Check to Time-of-Use (TOCTOU) bug in its DNS pre-flight validation mechanism. By returning a temporary resolution failure during validation and subsequently resolving to restricted IPs during HTTP execution, attackers can bypass security rules.
CodeWhale, an application developed by Hmbown, includes features to fetch remote content using URLs provided by users. To secure these features, CodeWhale implements a DNS pinning and pre-flight validation mechanism designed to prevent Server-Side Request Forgery (SSRF) attacks. The intended design checks hostnames prior to initiating external HTTP connections, validating their resolved IP addresses against local network restriction policies.
However, before version 0.8.64 (and version 0.8.41 in the legacy branch), the validation engine contained a severe logical flaw in its handling of pre-flight DNS resolution failures. Specifically, if the initial DNS resolution failed, the application silently ignored the failure and permitted the subsequent HTTP connection to proceed. This omission transforms the validation logic into a classic Time-of-Check to Time-of-Use (TOCTOU) vulnerability.
An attacker can exploit this behavior to bypass local network policies. By orchestrating a DNS configuration that fails during the validation check but succeeds during the actual fetch operation, the attacker can force the CodeWhale server to establish connections to internal loopback addresses, local network services, or cloud infrastructure metadata endpoints.
The vulnerability resides in crates/tui/src/tools/fetch_url.rs within the validate_fetch_target function. When validating a destination host, the function attempts to perform a DNS lookup using tokio::net::lookup_host. The underlying implementation is designed to verify that the target IP does not resolve to local loopback ranges, link-local addresses, or private subnets defined in the network policy.
If the DNS resolution succeeds, the application validates the returned IP addresses. If the DNS lookup fails and returns an error (such as std::io::ErrorKind::TimedOut or a temporary server failure), the original code caught the error but failed to abort the transaction. Instead, the function assumed that any hostname failing resolution during the check phase would inevitably fail during the actual request execution phase.
This assumption is fundamentally flawed. An attacker can control the DNS server authoritative for the target domain and respond differently during the pre-flight check and the actual HTTP request. By intentionally triggering a DNS resolution failure (such as returning SERVFAIL or dropping the query) during the validation check, the attacker coaxes the validation function into returning Ok(None), effectively bypassing all security checks.
Let us review the vulnerable implementation compared to the patch introduced in commit 26de44a8bd5051f8f944ea60b2c37ae1d2b7d25e. In the vulnerable code path, the DNS lookup was wrapped inside an if let Ok(addrs) pattern. If lookup_host returned an Err, the entire block was skipped, and Ok(first_valid.map(...)) returned Ok(None), bypassing validation.
// Pre-patch vulnerable implementation logic
let mut first_valid: Option<std::net::IpAddr> = None;
if let Ok(addrs) = tokio::net::lookup_host((host.as_str(), 0u16)).await {
for addr in addrs {
validate_dns_resolved_ip(&host, &addr.ip(), context.network_policy.as_ref())?;
if first_valid.is_none() {
first_valid = Some(addr.ip());
}
}
}
// If DNS resolution fails, the HTTP request was allowed to proceed
Ok(first_valid.map(|validated_ip| (host, validated_ip)))The patch explicitly changes this behavior. The lookup_host call is now chained with .map_err to immediately elevate any resolution failure to a ToolError::permission_denied error, aborting the execution. Furthermore, the patched code enforces that if no addresses are returned, the execution is terminated.
// Patched implementation in crates/tui/src/tools/fetch_url.rs
let addrs = tokio::net::lookup_host((host.as_str(), 0u16))
.await
.map_err(|e| {
ToolError::permission_denied(format!(
"could not resolve host before fetch_url request: {e}"
))
})?;
let mut first_valid: Option<std::net::IpAddr> = None;
for addr in addrs {
validate_dns_resolved_ip(&host, &addr.ip(), context.network_policy.as_ref())?;
if first_valid.is_none() {
first_valid = Some(addr.ip());
}
}
let Some(validated_ip) = first_valid else {
return Err(ToolError::permission_denied(
"host resolved to no addresses before fetch_url request",
));
};
Ok(Some((host, validated_ip)))While this patch successfully addresses the immediate TOCTOU bypass of a failing check, a sophisticated attacker could still leverage DNS Rebinding with short TTLs (Time-To-Live) if the HTTP client library conducts its own independent DNS resolution without using the pinned IP address retrieved during the pre-flight phase. Comprehensive mitigation requires pinning the resolved IP at the socket layer.
Exploiting this vulnerability requires the attacker to control the authoritative DNS server for a domain (e.g., ssrf.attacker.com) and a configuration that returns stateful responses. The attacker schedules the DNS server to behave differently across consecutive queries or implements a temporary denial-of-service/error state.
In step one, the attacker submits an API request to CodeWhale to fetch https://ssrf.attacker.com/metadata. CodeWhale executes the pre-flight validator, which queries ssrf.attacker.com. The attacker's DNS server drops the request or returns SERVFAIL. The validator catches the error, assumes the host is unresolvable, and permits the connection.
In step two, the HTTP client (reqwest) executes the actual GET request. It resolves ssrf.attacker.com once more. This time, the attacker's DNS server returns a valid local address, such as 127.0.0.1 or the AWS metadata endpoint 169.254.169.254. The HTTP client establishes a connection to the internal endpoint, completely bypassing the SSRF filters.
The security implications of an SSRF bypass of this nature are severe. An attacker can leverage the CodeWhale server as an entry point to scan the internal network, access internal APIs, and query local microservices that rely on network perimeter security for authentication.
In cloud environments, this vulnerability permits the retrieval of highly sensitive metadata, such as temporary IAM credentials from the Instance Metadata Service (IMDSv1) at 169.254.169.254. The vulnerability received a CVSS v4.0 base score of 9.2 (Critical), indicating high confidential impact on both the immediate system and subsequent systems (VC:H, SC:H) without requiring user interaction or elevated privileges.
Because the DNS resolution check failed silently, standard application logs would not easily capture the bypass attempt, making detection via basic request logging difficult without specialized network monitoring or DNS queries inspection.
Beyond resolving the TOCTOU SSRF flaw, commit 26de44a8bd5051f8f944ea60b2c37ae1d2b7d25e introduced critical security upgrades to protect local system boundaries. First, the image_analyze tool was hardened against directory traversal via symbolic links. The application previously verified paths syntactically but did not validate the resolution of symbolic links. The patch canonicalizes paths to ensure they stay within the workspace.
Second, the JavaScript execution tool was modified to prevent child scripts from inheriting the parent process's environment variables. This prevents execution containers from reading and leaking sensitive infrastructure secrets, such as API tokens. Users must upgrade to CodeWhale version 0.8.64 (or 0.8.41 on the older branch) to apply these fixes.
If upgrading is delayed, network-level egress filters should be implemented. Firewalls or container network policies must block the CodeWhale process from establishing connections to loopback addresses, private IP ranges (RFC 1918), and cloud metadata endpoints.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
CodeWhale Hmbown | >= 0.8.5, < 0.8.41 | 0.8.41 |
CodeWhale Hmbown | >= 0.8.41, < 0.8.64 | 0.8.64 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-918: Server-Side Request Forgery (SSRF) |
| Attack Vector | Network |
| CVSS v4.0 Score | 9.2 (Critical) |
| EPSS Score | 0.0037 (Percentile: 30.08%) |
| Impact | High Confidentiality Breach |
| Exploit Status | Proof-of-Concept in tests; no weaponized exploits |
| KEV Status | Not listed |
The web application fetches a resource without sufficiently validating the destination URI, allowing an attacker to coerce the server into sending requests to restricted internal network endpoints.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.