Two Dev.to articles compare memory-safety CVEs across Rust and C/C++. They argue that Rust’s ownership and borrowing model prevents many classes of memory-management bugs in “safe” code, while C and C++ commonly allow undefined behavior through manual memory management. The authors distinguish vulnerability categories: use-after-free, buffer overflows, and data races are characterized as common in C/C++ but impossible by design in Rust safe code; Rust safe code can still experience issues like integer overflow (with different behavior in debug vs. release) and logic bugs. They also emphasize limits: Rust guarantees do not extend into unsafe blocks, foreign-function interfaces (FFI) with C, or dependencies that use unsafe internally. The articles cite publicly verifiable sources rather than proprietary datasets, including the rustsec/advisory-db repository (used via cargo-audit), vulnerability distributions in the NVD/NIST by CWE categories for C/C++, and publicly referenced analyses from major vendors such as Chromium and Microsoft. Overall, they caution against using raw CVE counts alone to justify broad migration, stressing that relevance depends on threat models, integration with C, and the ability to review unsafe in critical dependencies.
Rust and C/C++ show different memory-safety CVE patterns due to language guarantees and unsafe boundaries
Two Dev.to articles compare memory-safety CVEs across Rust and C/C++. They argue that Rust’s ownership and borrowing model prevents many classes of memory-management bugs in “safe” code, while C and C...
- Rust safe code is described as preventing common memory-management bugs such as use-after-free, buffer overflow, and data races by design, while C/C++ are characterized as commonly affected.
- Both articles stress Rust’s guarantees are scoped: unsafe blocks, FFI with C, and dependencies that use unsafe fall outside Rust safe-code protections.
- The authors recommend using public data sources such as rustsec/advisory-db (via cargo-audit), and the NVD/CWE categorization to examine vulnerability distributions.
- They argue comparisons based only on CVE counts can be misleading because counts depend on factors like installed base and ecosystem differences.
- They caution that migrating existing code has high costs and that language choice should follow the specific threat model rather than security marketing.
How Memory Safety CVEs Differ Between Rust and C/C++ Why do we keep measuring language security by CVE count when we know that number depends as much on installed base size as on any actual property of the language? It took years of debate and a couple of NSA and CISA papers for the ecosystem to take the question seriously — and even then, the answer circulating in most threads is too simple to be useful. Here's my thesis: the difference in memory safety CVEs between Rust and C/C++ is real, documentable, and technically interesting. But turning it into "migrate everything to Rust" or "the borrow checker solves it all" is a category error. The useful data isn't in the headline — it's in which vulnerabilities disappear, which ones persist, and under what conditions Rust's security model has its own friction. The real problem: not all memory CVEs are the same When CISA, NSA, or the White House Office of the National Cyber Director publish reports recommending memory-safe languages (and they did, publicly, between 2022 and 2023), the category they're targeting is specific: vulnerabilities caused by undefined behavior in manual memory management. Use-after-free, buffer overflow, double-free, unchecked null pointer dereference — the classic C/C++ family. The technical distinction matters: Vulnerability class C/C++ Rust (safe) Rust (unsafe) Use-after-free Common Impossible by design Possible Buffer overflow (stack/heap) Common Impossible by design Possible Data race in multithreading Common Impossible by design Possible Integer overflow Possible Debug: panic / Release: wrapping Same Logic bugs Always possible Always possible Always possible Misused unsafe block N/A Possible Possible This table isn't a production benchmark — it's a map of what guarantees the Rust compiler gives you in safe code vs. what falls outside those guarantees. This isn't my own claim: the ownership model and borrow checker rules are formally described in The Rust Reference and in the unsafe chapter of the official book. The point most ignored in Twitter/HN discussions: roughly 70% of the code in a typical Rust project can live in safe, but any C integration via FFI, any unsafe block for low-level operations, and any crate dependency that uses unsafe internally falls right back into C territory. This isn't a hypothetical — libs like tokio, serde, and ring have reviewed and audited unsafe blocks, but the compiler's security contract doesn't apply there. Available evidence: what you can verify without access to someone else's production You don't need a proprietary CVE dataset to validate something concrete. There are at least three reproducible public sources: 1. RustSec Advisory Database The rustsec/advisory-db repository on GitHub maintains security advisories for the Rust ecosystem. It's auditable, has categories by vulnerability type and date. You can run: # Install cargo-audit if you don't have it cargo install cargo-audit # Audit dependencies of any Rust project cargo audit # View active advisories with detail cargo audit --json | jq '.vulnerabilities.list[] | {id: .advisory.id, title: .advisory.title, categories: .advisory.categories}' The output tells you not just whether there are known vulnerabilities, but what category they fall into. That data is concrete and reproducible on any machine. 2. CVE Details / NVD by CWE The NVD (National Vulnerability Database) categorizes CVEs by CWE (Common Weakness Enumeration). CWE-119 (buffer errors), CWE-416 (use-after-free), and CWE-476 (null pointer dereference) are the categories that concentrate the bulk of historical CVEs in C/C++ projects. You can filter by language and year at nvd.nist.gov and observe the distribution. The volume is asymmetric — and part of that asymmetry is installed base, not just language safety. 3. Chromium and Microsoft as public reference cases Google published internal data showing that ~70% of severe Chrome CVEs over a given period were memory safety issues in C++. Microsoft did the equivalent for their products. Those numbers get cited constantly, but context matters: these are C++ projects with tens of millions of lines and decades of technical debt. They're not representative of a new, well-audited C++ project. Where people get it wrong: the too-fast recipe The most common mistake I see in technical discussions is treating the CVE comparison as a direct adoption argument. The reasoning usually goes: "Rust has fewer memory CVEs → migrate the stack → problem solved." There are three costs that recipe hides: Cost 1: The invisible unsafe in dependencies. If you pull in a crates.io dependency without checking its advisories, you're potentially importing unaudited unsafe. cargo audit catches it if there's a registered advisory — but there's unsafe in crates without advisories because nobody's audited them yet. The borrow checker can't protect you from what it can't see. Cost 2: The unsafe curve in FFI. If the system you want to protect does FFI with C (drivers, hardware libraries, bindings to OpenSSL/libsodium), that interface is unsafe territory. A poorly written wrapper can introduce exactly the same bugs you were trying to avoid. Rust's guarantee ends at the boundary of the unsafe block. Cost 3: Logic bugs and business logic vulnerabilities. The borrow checker solves a specific class of bugs — memory management ones. A TOCTOU, a race condition in business logic, bad input validation, a broken permissions schema: none of those disappear by switching languages. This isn't an argument against Rust — it's an argument against believing the language holistically solves security. An honest read of this connects to something I've learned more than once looking at validation schemas: the place that hurts most isn't the one the compiler protects, it's the one you assume is covered and isn't. Same as when you write a Zod schema once and expect it to validate the entire flow — but there are three ways it breaks at runtime that aren't obvious until you see them. Decision matrix: when this data changes something and when it doesn't Before using the CVE comparison as a technical argument, run it through this checklist: CHECKLIST: Is the Rust vs C/C++ CVE data relevant to my decision? [ ] Does the system I'm evaluating have C/C++ with manual memory management? → If not, the comparison is irrelevant to you. [ ] Is the primary attack surface memory vulnerabilities (UAF, overflow)? → If the dominant risk is business logic or authentication, Rust doesn't change that. [ ] Do I have the capacity to review unsafe blocks in critical dependencies? → If not, the gain shrinks: you're importing opaque risk just like in C. [ ] Does the project use extensive FFI with C? → The borrow checker's benefit is scoped to the safe portion of the code. [ ] Am I evaluating new code vs. migrating existing code? → Migrating a large C/C++ codebase has real rewrite costs and a coexistence period. → New code in Rust on a well-scoped domain: the benefit is immediate and verifiable. [ ] Does the team have experience with the ownership model? → The borrow checker learning curve is real. A team without Rust experience can introduce more bugs during the transition than it avoids in the medium term. For projects where the domain is low-level computation, parsing untrusted binary formats, system daemons, or network components with high exposure, the argument for Rust is solid and backed by public evidence. For a business backend in TypeScript or Java where the dominant risk is injection, poorly implemented authentication, or broken permissions logic, the memory safety debate is almost a distraction. This connects to something that also applies to the authentication token decision tree: the right technical choice depends on the actual threat model, not on whichever language or protocol has the best security marketing. FAQ Does Rust eliminate all memory CVEs? No. It eliminates memory CVEs in safe code — which is the majority of code in a well-structured project. Any unsafe block, FFI with C, or external crate with unaudited unsafe falls outside that guarantee. The borrow checker is a contract with the compiler, not a global security scanner. Do Rust projects have zero memory safety CVEs? Not exactly. The public rustsec/advisory-db database has advisories for Rust projects, some with memory safety categories originating in unsafe blocks or in crates with bugs prior to an audit. They're fewer in absolute and proportional terms than in equivalent C/C++ projects, but "fewer" isn't "zero." Does it make sense to migrate a TypeScript/Node backend to Rust for security? In most cases, no. The threat model of a business backend isn't dominated by memory management vulnerabilities — it's dominated by authentication logic, input validation, and infrastructure configuration. Rust doesn't change that. The decision makes more sense for parsing components, cryptography, or low-level networking. What's the practical difference between a C/C++ CVE and a Rust one? Memory CVEs in C/C++ are typically directly exploitable: a buffer overflow can lead to arbitrary code execution. CVEs in Rust tend to be more contained — panic, memory leak, or incorrect behavior in edge cases — and less frequently escalate to arbitrary execution. That difference in average severity is technically significant even if the raw count is lower. Is cargo audit enough to audit a Rust project? It's a good first step, but it's not complete. It covers advisories registered in rustsec/advisory-db. It doesn't detect unaudited unsafe without an advisory, logic bugs, or vulnerabilities in system dependencies (dynamically linked C libraries). For a serious audit, you complement it with cargo-geiger (which counts and identifies unsafe across the dependency tree) and manual review of critical dependencies. Does any of this change things for someone working primarily with TypeScript/Next.js? Directly, not much. The relevant security model for that stack is different: schema validation, session management, HTTP headers, database permissions. Understanding the Rust/C++ comparison is useful for making architecture decisions when there are low-level components involved, or for evaluating whether a native dependency (a Node.js addon in C++) is worth the risk. It's not a day-to-day decision in a standard Next.js project. Closing: what the data says and what it can't say The difference in memory safety CVEs between Rust and C/C++ is a real phenomenon, documented in public sources and technically explainable by the compiler's ownership model. It's not hype — there's a structural reason why a certain class of bugs is impossible in Rust safe code. The uncomfortable part is that this data gets used constantly to justify decisions that are badly framed. If a system's threat model isn't dominated by manual memory management, the CVE comparison doesn't resolve anything. If the team doesn't have the capacity to review unsafe in dependencies, the compiler's guarantee dilutes in practice. My position after looking at this from multiple angles: Rust is a solid tool for specific domains where memory management is the primary risk. As a universal security argument, it falls short. The practical step I'd recommend before any decision: run cargo audit and cargo geiger on any Rust project you're considering adopting, look at what percentage of the dependency tree has unsafe, and decide with that number in hand — not with the headline. The same applies to architecture decisions in general: formal methods have a clear ceiling, and believing a tool holistically solves security is the most elegant way to drop your guard exactly where it matters most. This article was originally published on juanchi.dev
13 hours agoCómo difieren los CVEs de memory safety entre Rust y C/C++ ¿Por qué seguimos midiendo la seguridad de un lenguaje por cantidad de CVEs si sabemos que ese número depende tanto del tamaño de la base instalada como de cualquier propiedad del lenguaje en sí? Llevó años de debate y un par de papers de NSA y CISA para que el ecosistema tomara en serio la pregunta — y aun así, la respuesta que circula en la mayoría de los hilos es demasiado simple para ser útil. Mi tesis es esta: la diferencia en CVEs de memory safety entre Rust y C/C++ es real, documentable y técnicamente interesante. Pero convertirla en "migrá todo a Rust" o en "el borrow checker lo resuelve todo" es un error de categoría. El dato útil no está en el titular — está en qué tipo de vulnerabilidades desaparecen, cuáles persisten y bajo qué condiciones el modelo de seguridad de Rust tiene fricciones propias. El problema real: no todos los CVEs de memoria son iguales Cuando CISA, NSA o el White House Office of the National Cyber Director publican reportes recomendando lenguajes memory-safe (y lo hicieron de forma pública entre 2022 y 2023), la categoría que apuntan es específica: vulnerabilidades causadas por comportamiento indefinido en la gestión manual de memoria. Use-after-free, buffer overflow, double-free, null pointer dereference no chequeado — la familia clásica de C/C++. La distinción técnica importa: Clase de vulnerabilidad C/C++ Rust (safe) Rust (unsafe) Use-after-free Común Imposible por diseño Posible Buffer overflow (stack/heap) Común Imposible por diseño Posible Data race en multithreading Común Imposible por diseño Posible Integer overflow Posible Debug: panic / Release: wrapping Igual Logic bugs Siempre posible Siempre posible Siempre posible Unsafe block mal usado N/A Posible Posible La tabla no es un benchmark de producción — es un mapa de qué garantías da el compilador de Rust en código safe vs. qué queda fuera de esas garantías. La fuente no es un claim propio: el modelo de ownership y las reglas del borrow checker están descritos formalmente en The Rust Reference y en el capítulo de unsafe del libro oficial. El punto que más se ignora en las discusiones de Twitter/HN: aproximadamente el 70% del código en un proyecto Rust típico puede vivir en safe, pero cualquier integración con C via FFI, cualquier unsafe block para operaciones de bajo nivel, y cualquier dependencia de crate que use unsafe internamente recae en el mismo territorio de C. No es un problema hipotético — libs como tokio, serde y ring tienen bloques unsafe revisados y auditados, pero el contrato de seguridad del compilador no aplica ahí. Evidencia disponible: qué podés verificar sin tener acceso a producción ajena No hace falta un dataset de CVEs propietario para validar algo concreto. Hay al menos tres fuentes públicas reproducibles: 1. RustSec Advisory Database El repositorio rustsec/advisory-db en GitHub mantiene advisories de seguridad para el ecosistema Rust. Es auditable, tiene categorías por tipo de vulnerabilidad y fecha. Podés correr: # Instalar cargo-audit si no lo tenés cargo install cargo-audit # Auditar dependencias de cualquier proyecto Rust cargo audit # Ver advisories activos con detalle cargo audit --json | jq '.vulnerabilities.list[] | {id: .advisory.id, title: .advisory.title, categories: .advisory.categories}' El resultado te dice no solo si hay vulnerabilidades conocidas, sino de qué categoría son. Ese dato es concreto y reproducible en cualquier máquina. 2. CVE Details / NVD por CWE El NVD (National Vulnerability Database) categoriza CVEs por CWE (Common Weakness Enumeration). CWE-119 (buffer errors), CWE-416 (use-after-free) y CWE-476 (null pointer dereference) son las categorías que concentran la mayor parte de los CVEs históricos de proyectos C/C++. Podés filtrar por lenguaje y año en nvd.nist.gov y observar la distribución. El volumen es asimétrico — y parte de esa asimetría es base instalada, no solo seguridad del lenguaje. 3. Chromium y Microsoft como casos de referencia pública Google publicó datos internos mostrando que ~70% de los CVEs severos de Chrome en un período dado eran memory safety issues en C++. Microsoft hizo lo equivalente para sus productos. Esos números son citados frecuentemente, pero el contexto importa: son proyectos C++ de decenas de millones de líneas, con décadas de deuda técnica. No son representativos de un proyecto C++ nuevo y bien auditado. Donde se equivoca la gente: la receta demasiado rápida El error más común que veo en discusiones técnicas es tratar la comparación de CVEs como un argumento de adopción directa. El razonamiento suele ser: "Rust tiene menos CVEs de memoria → migrá el stack → problema resuelto." Hay tres costos que esa receta oculta: Costo 1: El unsafe invisible de las dependencias. Si tomás una dependencia de crates.io sin revisar sus advisories, estás importando potencialmente unsafe no auditado. cargo audit lo detecta si hay un advisory registrado — pero hay unsafe en crates sin advisory porque nadie lo auditó todavía. El borrow checker no te protege de lo que no ve. Costo 2: La curva de unsafe en FFI. Si el sistema que querés proteger hace FFI con C (drivers, librerías de hardware, bindings a OpenSSL/libsodium), esa interfaz es territorio unsafe. Un wrapper mal escrito puede introducir exactamente los mismos bugs que querías evitar. La garantía de Rust termina en la frontera del bloque unsafe. Costo 3: Logic bugs y vulnerabilidades de lógica de negocio. El borrow checker resuelve una clase específica de bugs — los de gestión de memoria. Un TOCTOU, una condición de carrera en lógica de negocio, una validación de input mal hecha, un schema de permisos incorrecto: ninguno de esos desaparece por cambiar de lenguaje. Esto no es un argumento en contra de Rust — es un argumento en contra de creer que el lenguaje resuelve la seguridad de forma holística. Una lectura honesta de esto me conecta con algo que aprendí más de una vez mirando esquemas de validación: el lugar donde más duele no es el que protege el compilador, sino el que asumís que está cubierto y no está. Igual que cuando creés un schema Zod una vez y esperás que valide todo el flujo — pero hay tres formas en que se rompe en runtime que no son obvias hasta que las ves. Matriz de decisión: cuándo este dato cambia algo y cuándo no Antes de usar la comparación de CVEs como argumento técnico, pasala por esta checklist: CHECKLIST: ¿El dato de CVEs de Rust vs C/C++ es relevante para mi decisión? [ ] ¿El sistema que estoy evaluando tiene C/C++ con gestión manual de memoria? → Si no, la comparación es irrelevante para vos. [ ] ¿La superficie de ataque principal son vulnerabilidades de memoria (UAF, overflow)? → Si el riesgo dominante es lógica de negocio o autenticación, Rust no cambia eso. [ ] ¿Tengo capacidad de revisar unsafe blocks en dependencias críticas? → Si no, la ganancia se reduce: importás riesgo opaco igual que en C. [ ] ¿El proyecto usa FFI extensivo con C? → El beneficio del borrow checker se acota a la porción safe del código. [ ] ¿Estoy evaluando código nuevo vs. migrar código existente? → Migrar una base C/C++ grande tiene un costo real de reescritura y periodo de coexistencia. → Código nuevo en Rust sobre un dominio bien acotado: el beneficio es inmediato y verificable. [ ] ¿El equipo tiene experiencia con el modelo de ownership? → La curva de aprendizaje del borrow checker es real. Un equipo sin experiencia en Rust puede introducir más bugs durante la transición que los que evita a mediano plazo. Para proyectos donde el dominio es computación de bajo nivel, parsing de formatos binarios no confiables, daemons de sistema o componentes de red con alta exposición, el argumento a favor de Rust es sólido y respaldado por evidencia pública. Para un backend de negocio en TypeScript o Java donde el riesgo dominante es inyección, autenticación mal implementada o lógica de permisos rota, el debate de memory safety es casi una distracción. Esto conecta con algo que también aplica al árbol de decisión de tokens de autenticación: la elección técnica correcta depende del threat model real, no del lenguaje o protocolo con mejor marketing de seguridad. FAQ ¿Rust elimina todos los CVEs de memoria? No. Elimina los CVEs de memoria en código safe — que es la mayoría del código de un proyecto bien estructurado. Cualquier bloque unsafe, FFI con C, o crate externo con unsafe no auditado queda fuera de esa garantía. El borrow checker es un contrato con el compilador, no un escáner de seguridad global. ¿Los proyectos Rust tienen cero CVEs de memory safety? No exactamente. La base de datos pública rustsec/advisory-db tiene advisories de proyectos Rust, algunos con categorías de memory safety originadas en bloques unsafe o en crates con bugs previos a una auditoría. Son menos en términos absolutos y proporcionales que en proyectos C/C++ equivalentes, pero "menos" no es "cero". ¿Tiene sentido migrar un backend TypeScript/Node a Rust por seguridad? En la mayoría de los casos, no. El threat model de un backend de negocio no está dominado por vulnerabilidades de gestión de memoria — está dominado por lógica de autenticación, validación de input y configuración de infraestructura. Rust no cambia eso. La decisión tiene más sentido para componentes de parsing, criptografía o networking de bajo nivel. ¿Qué diferencia hay entre un CVE de C/C++ y uno de Rust en la práctica? Los CVEs de C/C++ en memoria suelen ser explotables directamente: un buffer overflow puede llevar a ejecución de código arbitrario. Los CVEs en Rust tienden a ser más acotados — panic, leak de memoria, o comportamiento incorrecto en edge cases — y menos frecuentemente escalan a ejecución arbitraria. Esa diferencia de severidad promedio es técnicamente significativa aunque el conteo bruto sea menor. ¿cargo audit es suficiente para auditar un proyecto Rust? Es un buen primer paso, pero no es completo. Cubre advisories registrados en rustsec/advisory-db. No detecta unsafe no auditado sin advisory, bugs lógicos, ni vulnerabilidades en dependencias de sistema (librerías C enlazadas dinámicamente). Para una auditoría seria, se complementa con cargo-geiger (que cuenta e identifica unsafe en el árbol de dependencias) y revisión manual de las dependencias críticas. ¿Esto cambia algo para alguien que trabaja principalmente con TypeScript/Next.js? Directamente, poco. El modelo de seguridad relevante para ese stack es diferente: validación de esquemas, gestión de sesiones, headers HTTP, permisos de base de datos. Entender la comparación Rust/C++ es útil para tomar decisiones de arquitectura cuando hay componentes de bajo nivel o para evaluar si una dependencia nativa (un addon Node.js en C++) vale el riesgo. No es una decisión cotidiana en un proyecto Next.js estándar. Cierre: lo que el dato dice y lo que no puede decir La diferencia en CVEs de memory safety entre Rust y C/C++ es un fenómeno real, documentado en fuentes públicas y técnicamente explicable por el modelo de ownership del compilador. No es hype — hay una razón estructural por la que cierta clase de bugs es imposible en código Rust safe. Lo incómodo es que ese dato se usa frecuentemente para justificar decisiones que están mal planteadas. Si el threat model de un sistema no está dominado por gestión manual de memoria, la comparación de CVEs no resuelve nada. Si el equipo no tiene capacidad de revisar unsafe en dependencias, la garantía del compilador se diluye en la práctica. Mi postura después de mirar esto desde varios ángulos: Rust es una herramienta sólida para dominios específicos donde la gestión de memoria es el riesgo principal. Como argumento universal de seguridad, es insuficiente. El paso práctico que recomendaría antes de cualquier decisión: corré cargo audit y cargo geiger en cualquier proyecto Rust que estés evaluando adoptar, mirá qué porcentaje del árbol de dependencias tiene unsafe, y decidí con ese número en la mano — no con el titular. Lo mismo aplica a decisiones de arquitectura en general: los métodos formales tienen un techo claro, y creer que una herramienta resuelve la seguridad de forma holística es la forma más elegante de bajar la guardia donde más importa. Este artículo fue publicado originalmente en juanchi.dev
13 hours agoBarkly Rare Earths wins second NT Government exploration grant for expansion drilling
Barkly Rare Earths receives a second exploration grant from the Northern Territory Government, securing $115,000 for exp...
HPE offers VMware users a free first year of Morpheus VM Essentials
Hewlett Packard Enterprise (HPE) is promoting its Morpheus Software—VM Essentials as an alternative to VMware by offerin...
iPhone 18 rumored to include 12GB RAM to unlock advanced Siri AI features
Multiple outlets report renewed speculation that Apple’s next base iPhone, the iPhone 18, will ship with 12GB of RAM. Th...