The curl networking library, written in C and used in everything from cars to spacecraft, has been under unusually heavy public scrutiny this year as language models surface flaws a human reviewer might miss. The story isn't that curl is sloppy. Its maintainers, led by Daniel Stenberg, are among the most careful in open source. The story is what the kind of flaw being found says about the substrate it sits on, as laid out in a June 15 analysis of memory-safety CVEs by Rust contributor Kobzol.
A CVE, or Common Vulnerabilities and Exposures entry, is a publicly catalogued software flaw with a unique identifier. Memory safety, in plain terms, means preventing a program from reading or writing memory it shouldn't, the class of bug behind many of the most serious security problems in modern software. What Kobzol argues in the post is that comparing raw CVE counts between Rust and C or C++ measures the wrong thing. The same shape of bug, a function called with the wrong input, gets filed against one library as a soundness hole and against another as caller misuse. The count looks like a scorecard. The underlying picture is asymmetry.
The example Kobzol uses is concrete. Libcurl, the C library that powers the curl command line tool, exports a function called curl_getenv. Calling it from C with a null argument compiles cleanly and segfaults at runtime, because the function does not handle that case. By libcurl's own accounting, this is not a libcurl bug. It is treated as caller error. The same shape of mistake against a safe Rust API, where a function expects a non-null option but is called with None, would by Rust's norms be filed as a soundness hole in the library. The function promised safety in its signature. The implementation failed to deliver. A CVE follows.
The mechanism behind that asymmetry is the unsafe keyword in Rust. Unsafe is an explicit, lexically marked boundary in the source code. A reviewer can grep for it. Memory unsafety in C and C++, by contrast, is the default substrate of every translation unit. There is no marker to grep for because there is nothing to opt into. When a memory-safety CVE lands against a C library, the bug can live anywhere in the codebase by default. When it lands against a Rust crate and the path from safe code reaches an unsafe block, the unsafe block is, in effect, named as the suspect.
That distinction matters because it turns memory safety from a tribal language argument into a tractable audit, supply chain, and procurement problem. A team assessing a dependency can ask, in any language: where do memory accesses happen, is the surface bounded, and what does the review contract around that surface look like? The answer is not a verdict on which language to adopt. It is a question about the artifact in front of you.
Two caveats are worth holding onto. The first is that Rust's memory-safety guarantee attaches to its safe APIs. The unsafe keyword is only as good as the review around it, and projects like cve-rs have demonstrated real Rust soundness bugs traced back to unsafe code. The second is that C and C++ have decades of mature hardening tooling, sanitizers like ASan, and fuzzing infrastructure that audit and procurement processes can lean on, even if the language itself does not make memory safety a default. Neither caveat erases the distinction. Both keep it honest.
The recent wave of LLM-discovered CVEs is a real signal worth taking seriously, not noise to be waved away. In a May 26 blog post, Stenberg described the incoming rate of security reports to curl as 4–5 times higher than in 2024, with more than one report per day arriving on average — a development he linked directly to AI-powered security scanning tools. The question it raises is not which language produces fewer CVEs. It is what shape the bugs being found have, what review surface they sit on, and what a buyer, reviewer, or security lead can do with that information. Read the CVE. Ask whether the bug was opt-in or default. The answer, more often than the count, is the audit signal.