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:

  1. libcurl (C): curl_getenv(NULL) produce un segfault sin advertencia del compilador, pero este comportamiento no se considera un CVE en curl porque:
– El contrato de la API no documenta explícitamente que 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.

  1. 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 usa unsafe. Esto ocurre porque:
– Rust garantiza que las APIs seguras no pueden causar comportamiento indefinido (UB) por diseño.

– 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:
Menor tolerancia a bugs latentes: Un CVE en hyper (Rust) podría requerir parche inmediato, incluso si no hay exploits conocidos, porque el UB es posible por diseño.

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:
– Herramientas como 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:
– El 68% de los CVEs en C/C++ eran por UB o buffer overflows, pero solo el 12% fueron parcheados en la biblioteca (el resto se atribuyeron a «uso incorrecto»).

– 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:
| Lenguaje | CVEs por UB en libs | CVEs por UB en apps | Riesgo real |

|———-|———————-|———————|————-|

| 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_PRELOAD para 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:
– La función no valida el puntero de entrada.

– 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:
– Si la función es parte de una API segura (sin 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

CriterioC/C++Rust
**Contrato de la API**Implícito, no expresableExpresable via tipos y traits
**Responsabilidad**Usuario (uso incorrecto)Biblioteca (si es API segura)
**Detectabilidad**Compilador no advierteCompilador emite errores en tiempo de compilación
**Exploitability**Depende del contexto de usoSiempre explotable si hay UB
**CVEs por UB**~12% de los totales~95% de los totales
## Qué deberían hacer los administradores y equipos técnicos

Para equipos que usan Rust

  1. Configurar herramientas de auditoría:
– Usar 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"]
       
  1. Auditar dependencias transitivas:
– Verificar que bibliotecas como 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.

  1. Mitigación temporal:
– Si un CVE en Rust afecta un componente crítico (ej: balanceador HTTP), usar feature flags para deshabilitar la funcionalidad vulnerable:
     [dependencies]
     hyper = { version = "1.4.0", features = ["client"] } # Deshabilita server si es vulnerable
     

Para equipos que usan C/C++

  1. Auditar contratos de APIs:
– Documentar explícitamente los invariantes de funciones críticas (ej: «este puntero no puede ser NULL»). Ejemplo en 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);
     
  1. Usar sanitizadores estáticos:
– Herramientas como clang-tidy con reglas de undefined behavior:
     clang-tidy -checks='-*,bugprone-*,security-*' src/curl_getenv.c
     
  1. Mitigación en producción:
– Para CVEs por UB en bibliotecas como OpenSSL, usar LD_PRELOAD con wrappers seguros:
     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

  1. Políticas de actualización:
– En entornos Kubernetes, usar admission controllers para bloquear imágenes con CVEs en Rust no parcheados:
     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"
     
  1. Integración con Helm:
– Para charts que dependen de Rust, añadir hooks de verificación:
     # 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:

  1. Los CVEs en Rust son más precisos: Indican un defecto en el diseño seguro, no en su uso.
  2. 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.
  3. 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

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *