On October 11, 2023, curl maintainer Daniel Stenberg disclosed CVE-2023-38545, a heap buffer overflow in libcurl's SOCKS5 proxy handshake that the project itself flagged in advance as its worst security flaw in years. The bug had been sitting in the codebase since libcurl 7.69.0, shipped in March 2020, and wasn't fixed until 8.4.0 landed on October 11, 2023 — more than three and a half years of exposure in a library that ships inside curl the CLI tool, countless language bindings (PycURL, Node's node-libcurl, PHP's cURL extension), and embedded firmware from vendors including Siemens and NetApp. NVD scored it CVSS 3.1 9.8 Critical, while CISA's own scoring came in at 8.8 High, largely because the two disagreed on whether user interaction was required. Either way, it's tracked under CWE-787, Out-of-bounds Write — the same weakness class behind Heartbleed-era buffer bugs, though the root cause here is far simpler: a state-machine variable ends up with the wrong value. This piece walks through exactly what went wrong, who was affected, and how to find and fix it in your own dependency tree.
What exactly is the root cause of CVE-2023-38545?
The root cause sits in how curl decides who resolves a SOCKS5 proxy's target hostname. Normally curl hands the hostname to the proxy for remote resolution, which works for names up to 255 bytes. When a hostname is longer than that, curl instead resolves it locally itself and passes only the short resolved address on to the proxy — a slower path because it now involves a local DNS lookup. After curl's SOCKS5 handshake code was rewritten as a non-blocking state machine, a local variable meant to signal "resolve this locally" could be left with the wrong value during a sufficiently slow handshake. When that happened, curl skipped the intended substitution and copied the original, oversized hostname into the buffer meant to hold only the short resolved address — the same heap-based buffer libcurl reuses for downloads and SOCKS negotiation. A hostname longer than that buffer overflows it, corrupting adjacent heap memory. curl's own advisory (curl.se/docs/CVE-2023-38545.html) attributes the bug to that state-machine variable getting the wrong value during a slow handshake — a straightforward implementation bug rather than a novel exploitation primitive, which is part of why it went unnoticed through so many releases.
Which versions and products were actually affected?
libcurl versions 7.69.0 through 8.3.x were vulnerable; 8.4.0, released October 11, 2023, contains the fix. Because libcurl is one of the most widely embedded C libraries in existence — bundled into everything from mobile OS network stacks to industrial controllers — the blast radius extended well past people who ran curl directly. NVD's CVE-2023-38545 record lists downstream advisories from Siemens (affecting RUGGEDCOM APE1808 and SIMATIC/SIPLUS S7-1500 CPU variants that bundle vulnerable curl), NetApp (Active IQ Unified Manager, OnCommand Insight, and OnCommand Workflow Automation), Apple, and Fedora, alongside general Linux distribution advisories. The exploit path requires curl to be configured against a SOCKS5 proxy with hostname resolution happening on the client side — a specific but far from rare configuration, especially for tools proxying traffic through Tor or corporate SOCKS gateways. Because curl is so often a transitive dependency — pulled in by a Python package's bundled binary wheel, a Node native module, or a base container image — many affected teams didn't know they shipped it at all.
Why did NVD and CISA disagree on the severity score?
NVD scored CVE-2023-38545 at 9.8 (Critical) using the vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H — no user interaction required. CISA's ADP scoring assigned 8.8 (High) with UI:R, requiring user interaction. The difference comes down to how each scorer models the attack: triggering the overflow requires curl to actually be pointed at a SOCKS5 proxy and asked to resolve a sufficiently long hostname, which some scorers treat as a form of interaction or configuration precondition rather than a fully remote, zero-click path. This kind of scoring divergence is common enough that Vulnerability Management programs which key severity purely off a single CVSS number from a single source can misjudge urgency; cross-referencing NVD, CISA's ADP score, and vendor-specific advisories together gives a more complete picture than trusting one source's vector string.
How would this vulnerability actually be exploited?
Exploitation targets applications that use curl or libcurl configured with SOCKS5 proxying where hostname resolution happens locally rather than on the proxy. An attacker who can influence the target hostname a client curl call will resolve — for instance, through a redirect, a malicious upstream service, or a crafted URL passed to a proxying application — can supply a hostname long enough to overflow the undersized heap buffer, corrupting adjacent heap metadata or data. Proof-of-concept code demonstrating the crash appeared on GitHub within days of disclosure, though public writeups at the time noted that turning the overflow into reliable remote code execution required navigating memory allocator specifics that vary by platform and libc version — meaning real-world weaponization difficulty differed from installation to installation even though the underlying bug was identical everywhere.
How should teams detect and remediate this in practice?
Remediation is straightforward once you know curl is present: upgrade to libcurl 8.4.0 or later, or apply the vendor backport if you're on a distribution that patches CVEs without bumping the upstream version number (Fedora, Debian, and others shipped backported fixes rather than waiting for a full version bump). The harder problem is discovery, because curl frequently isn't a direct dependency you'd see in a requirements.txt or package.json — it's a shared library pulled in transitively by HTTP client bindings, container base images, or compiled extensions. A software composition analysis pass that only checks your direct manifest will miss it; you need dependency resolution deep enough to catch curl bundled several layers down, plus reachability context to confirm whether your actual code path uses SOCKS5 proxying with local hostname resolution — the specific precondition the bug requires — versus a direct HTTP path that never touches the vulnerable code at all.
How Safeguard Helps
Safeguard's deep dependency scanning walks transitive dependency graphs well past the first level, which matters for a library like libcurl that's routinely bundled inside compiled extensions and container base layers rather than declared directly. Once a vulnerable libcurl version is identified, Safeguard's SCA engine matches it against NVD, GHSA, and OSV records — pulling in both NVD's 9.8 and CISA's 8.8 scoring context rather than surfacing a single number — and layers in EPSS and CISA KEV signal to help teams judge real-world exploitation likelihood, not just theoretical severity. Reachability analysis then narrows the finding further: if your code path never configures a SOCKS5 proxy with local hostname resolution, that context is surfaced alongside the finding so teams can deprioritize non-reachable instances instead of treating every embedded libcurl copy in the fleet as equally urgent.