#Vulnerabilities

Rust and C CVEs measure different risks

Tech Essays Reporter
3 min read

Kobzol argues that Rust teams report soundness bugs as library flaws, while C teams treat many memory crashes as caller mistakes.

Kobzol's post explains a gap in how security teams count memory safety flaws in Rust and C or C++. Raw CVE counts can mislead you because the two language communities assign blame under different rules.

Security teams use CVE records to track reported vulnerabilities. In C and C++, maintainers often treat many memory faults as API misuse. A caller passes NULL to a function that expects a valid pointer, the program crashes, and maintainers blame the caller unless the docs or contract promised support for that input.

Kobzol uses libcurl as the example. A C program can call curl_getenv(NULL), compile cleanly, and crash at runtime. The crash demonstrates memory unsafety, but curl maintainers would have little reason to accept that report as a curl CVE. C gives library authors weak tools for encoding preconditions in function signatures, and C programmers accept that callers must know many unwritten rules.

Rust teams use a stricter standard. If a programmer writes safe Rust and triggers undefined behavior through a library API, Rust developers call that a soundness bug in the library. The caller did not opt into unsafe, so the library author broke the contract that safe Rust cannot cause memory unsafety.

That rule changes CVE meaning. A Rust CVE can describe a safe API that permits memory corruption under some input pattern, even before attackers exploit that pattern in a deployed program. A comparable C API might draw no CVE because C programmers expect the caller to avoid bad inputs.

The distinction comes from Rust's boundary between safe and unsafe code. Rust programmers mark risky operations with unsafe, and reviewers can focus attention on those blocks. Library authors may still use unsafe internals, but they must hide that risk behind safe abstractions. The Rustonomicon exists because those abstractions demand care.

C and C++ lack that shared boundary. A careful team can write robust C, and curl's maintainers have done that work for decades. Still, each application team can misuse a pointer, violate a lifetime rule, or pass an invalid buffer. The library author cannot force the compiler to reject many of those calls.

Kobzol's core argument lands on measurement. If you compare Rust and C or C++ by CVE counts alone, you mix two reporting cultures. Rust maintainers count some potential safe-API soundness holes as library vulnerabilities. C maintainers often reserve CVEs for concrete misuse patterns or flaws that violate an API's stated contract.

That does not make Rust immune to vulnerabilities. Rust programmers can write logic bugs, expose admin panels, or create undefined behavior inside unsafe code. Compiler bugs can also break the model. The claim has a narrower scope: safe Rust gives application developers a stronger default contract, and Rust maintainers treat violations of that contract as library bugs.

The counterpoint concerns fairness. Some C developers may argue that Rust CVE reports inflate risk by counting bugs that C projects would classify as caller misuse. Kobzol's answer: the stricter standard reflects Rust's value. Rust lets teams move memory safety responsibility from scattered application call sites into the smaller set of unsafe implementations that maintainers can audit and fix.

The practical lesson for security reviews: read CVEs by language context. A Rust soundness CVE often says, "A safe API allowed a memory bug." A C CVE often says, "A program hit a dangerous behavior under a specific path." Those labels share a database, but they do not measure the same engineering burden.

Comments

Loading comments...