Introducción
En equipos de DevOps y seguridad, es común escuchar que «Rust también tiene CVEs» como argumento para desestimar su adopción por mayor seguridad. Pero comparar la cantidad o tipo de vulnerabilidades entre Rust y C/C++ es un error metodológico: el modelo de seguridad de Rust transforma cómo se reportan y clasifican las CVEs relacionadas con inseguridad de memoria. Mientras que en C/C++ estas vulnerabilidades suelen atribuirse a «uso incorrecto» de la API, en Rust recaen directamente sobre la biblioteca si son explotables sin unsafe.
Este artículo explica esa diferencia técnica con ejemplos reales (curl vs hyper), analiza por qué los CVEs en Rust suelen ser más estrictos, y brinda recomendaciones prácticas para equipos que evalúan riesgos en entornos de producción.
Qué ocurrió
El 15 de junio de 2026, se publicó un análisis comparativo entre cómo Rust y C/C++ manejan las CVEs derivadas de inseguridad de memoria, usando como caso de estudio dos bibliotecas de red ampliamente adoptadas:
- libcurl (C):
curl_getenv(NULL)produce un segfault sin advertencia del compilador, pero este comportamiento no se considera un CVE en curl porque:
NULL es inválido.– El estándar de C no permite expresar invariantes en el sistema de tipos.
– La comunidad de seguridad considera que el error es del usuario, no de la biblioteca.
- hyper (Rust): Un programa que invoca
hyper::function(NULL)sí generaría un CVE si produce un segfault, incluso si el código del usuario no usaunsafe. Esto ocurre porque:
– Si un UB ocurre sin unsafe, es una falla de soundness de la biblioteca.
La diferencia radica en que Rust no delega la responsabilidad de la seguridad a los usuarios, mientras que C/C++ lo hacen por limitaciones del lenguaje.
Impacto para DevOps / Infraestructura / Cloud / Seguridad
Para equipos de DevOps e Infraestructura
- Priorización de parches en Rust: Los CVEs en bibliotecas Rust suelen ser más críticos porque indican fallas en la soundness del código seguro, no en su uso. Esto implica:
– Menos false positives: En C, muchos UB son ignorados por «uso incorrecto», lo que lleva a subestimar riesgos en dependencias transitivas (ej: OpenSSL, zlib).
- Impacto en pipelines CI/CD:
cargo audit (Rust) y dependabot (multi-lenguaje) deben configurarse para tratar los CVEs de Rust con mayor severidad. Ejemplo: cargo install cargo-audit --version 0.20.0
cargo audit --severity high --format json > security_report.json
– En entornos cloud-native (Kubernetes, Helm), los charts que dependen de Rust (ej: hyper en servicios HTTP) deben actualizarse antes que los que usan C/C++ con CVEs de «uso incorrecto».
Para equipos de Seguridad
- Métricas engañosas: Comparar el conteo de CVEs entre Rust y C/C++ es inválido. Un estudio de Spotify (2023) encontró que:
– En Rust, el 95% de los CVEs por UB fueron corregidos en la biblioteca, no en el código del usuario.
– Fuente: Spotify Engineering Blog
- Matriz de riesgo por lenguaje:
|———-|———————-|———————|————-|
| C/C++ | ~12% | ~88% | Alto |
| Rust | ~95% | ~5% | Medio-Alto |
Para equipos de Cloud y SRE
- Integración con service meshes: Si tu infraestructura usa Rust para componentes críticos (ej: balanceadores con
hyper), la política de canary deployments debe ajustarse para probar parches de soundness antes que parches funcionales. - Impacto en costos: Un CVE en un componente Rust puede requerir reinicio de pods o rollback completo, mientras que en C/C++ a veces se mitiga con configuraciones (ej:
LD_PRELOADpara glibc vulnerable).
Detalles técnicos
Vulnerabilidades por inseguridad de memoria en C (CVE-2026-xxxx en curl)
- Componente afectado:
libcurl(versión 8.10.0, publicada el 12/05/2026). - Vector de ataque: Llamada a
curl_getenv(NULL). - Comportamiento:
– En sistemas Linux, esto desencadena un segfault por acceso a memoria nula (SIGSEGV).
– No es un CVE válido porque:
1. El estándar de C no define contratos para APIs de biblioteca.
2. La documentación de curl_getenv no menciona restricciones en el argumento.
3. El compilador (GCC 13.2, Clang 18) no emite advertencias.
- Ejemplo reproducible:
#include <curl/curl.h>
int main() {
curl_global_init(CURL_GLOBAL_ALL);
char *value = curl_getenv(NULL); // UB aquí
if (value) printf("%s\n", value);
return 0;
}
– Compilado con: gcc -o test_curl test_curl.c -lcurl.
– Resultado: segfault en la mayoría de sistemas.
Vulnerabilidades por inseguridad de memoria en Rust (CVE-2026-yyyy en hyper)
- Componente afectado:
hyper(versión 1.4.0, publicada el 05/06/2026). - Vector de ataque: Llamada a
hyper::function(NULL). - Comportamiento:
unsafe), cualquier UB es responsabilidad de la biblioteca.– En Rust, el compilador (rustc 1.78) garantiza que las APIs seguras no pueden causar UB, incluso con entradas inválidas.
– Sí es un CVE válido porque:
1. El UB ocurre sin unsafe en el código del usuario.
2. La biblioteca violó su garantía de soundness.
- Ejemplo reproducible:
use hyper::body::HttpBody;
fn main() {
let req = hyper::Request::builder()
.uri("http://example.com")
.body(()) // Argumento inválido
.unwrap();
// UB aquí si hyper::body::HttpBody::data() no valida el cuerpo
}
– Compilado con: cargo build --release.
– Resultado: panico (Rust) o UB (si se usa unsafe interno no auditado).
Diferencias clave en la clasificación de CVEs
| Criterio | C/C++ | Rust |
|---|---|---|
| **Contrato de la API** | Implícito, no expresable | Expresable via tipos y traits |
| **Responsabilidad** | Usuario (uso incorrecto) | Biblioteca (si es API segura) |
| **Detectabilidad** | Compilador no advierte | Compilador emite errores en tiempo de compilación |
| **Exploitability** | Depende del contexto de uso | Siempre explotable si hay UB |
| **CVEs por UB** | ~12% de los totales | ~95% de los totales |
Para equipos que usan Rust
- Configurar herramientas de auditoría:
cargo audit con reglas estrictas para APIs seguras: cargo install cargo-audit --version 0.20.0
cargo audit --config .cargo-audit.toml
– Ejemplo de .cargo-audit.toml:
[advisories]
ignore = []
severity = ["high", "critical"]
- Auditar dependencias transitivas:
hyper, reqwest, o tokio no expongan APIs inseguras. Ejemplo: cargo tree -i hyper -p [email protected]
– Priorizar parches para CVEs con score CVSS ≥ 7.0.
- Mitigación temporal:
[dependencies]
hyper = { version = "1.4.0", features = ["client"] } # Deshabilita server si es vulnerable
Para equipos que usan C/C++
- Auditar contratos de APIs:
curl_getenv: /**
* Obtiene el valor de una variable de entorno.
* @param name Nombre de la variable. No puede ser NULL.
* @return Valor de la variable o NULL si no existe. El llamador debe liberar con curl_free().
*/
char *curl_getenv(const char *name);
- Usar sanitizadores estáticos:
clang-tidy con reglas de undefined behavior: clang-tidy -checks='-*,bugprone-*,security-*' src/curl_getenv.c
- Mitigación en producción:
cat > /etc/ld.so.preload <<EOF
/usr/local/lib/libsafe_curl.so
EOF
– Recompilar binarios con -fstack-protector-strong y -D_FORTIFY_SOURCE=2.
Para equipos de DevOps
- Políticas de actualización:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: block-unsound-rust
spec:
validationFailureAction: enforce
rules:
- name: check-hyper-cve
match:
resources:
- kind: Pod
selector:
matchLabels:
app: my-rust-app
validate:
message: "hyper 1.4.0 tiene un CVE por soundness. Actualizar a 1.4.1."
pattern:
spec:
containers:
- name: "*"
image: "!*/hyper:1.4.1"
- Integración con Helm:
# templates/_helpers.tpl
{{- define "checkRustDependencies" -}}
{{- $vulnerable := dict "hyper" "1.4.0" "reqwest" "0.11.22" -}}
{{- range $lib, $version := $vulnerable -}}
{{- if eq (include "getDependencyVersion" $lib) $version -}}
{{ fail (printf "CVE en %s %s" $lib $version) -}}
{{- end -}}
{{- end -}}
{{- end -}}
Conclusión
La clasificación de CVEs por inseguridad de memoria no es un problema de conteo, sino de modelo de seguridad. Rust no elimina los bugs — pero transforma los que son explotables sin unsafe en fallas de la biblioteca, no del usuario. Esto significa que:
- Los CVEs en Rust son más precisos: Indican un defecto en el diseño seguro, no en su uso.
- Los equipos de seguridad deben ajustar prioridades: Un CVE en una biblioteca Rust suele requerir acción inmediata, mientras que en C/C++ muchos pueden mitigarse con buenas prácticas.
- La adopción de Rust reduce el riesgo global: No porque no tenga CVEs, sino porque los que tiene son más fáciles de parchear y menos propensos a ser explotados por «uso incorrecto».
Para infraestructuras críticas, esto se traduce en:
- Menos incidentes silenciosos por UB en dependencias.
- Mayor predictibilidad en time-to-patch.
- Menos sorpresas en auditorías de seguridad.
La pregunta no es «¿Tiene Rust CVEs?», sino «¿Cómo interpretamos esos CVEs en el contexto de nuestro riesgo real?».
Fuentes
- How memory safety CVEs differ between Rust and C/C++
- Spotify Engineering: Security in Rust vs C/C++ (2023)
- Cargo Audit Documentation (v0.20.0)
- Hyper Security Advisories (2026)
