Volver a todos los posts
Release

El SAST para Rust es puro teatro. Acabamos de lanzar el de verdad.

La mayoría del SAST para Rust es coincidencia de patrones que omite errores reales. Mejora la seguridad de Rust con análisis de flujo de datos.

En esta página
  1. Por qué Rust merece un escaneo de seguridad real
  2. Por qué la mayoría del SAST para Rust es teatro de coincidencia de patrones
  3. Flujo de datos frente a coincidencia de patrones, en un ejemplo
  4. Qué detecta un conjunto de reglas para Rust consciente del flujo de datos
  5. Dentro del bucle del agente, no solo en el panel
  6. Preguntas frecuentes
  7. ¿Es suficiente la seguridad de memoria de Rust para prevenir vulnerabilidades?
  8. ¿Puede ocurrir inyección SQL en Rust con sqlx o diesel?
  9. ¿Por qué las herramientas de SAST para Rust producen tantos falsos positivos?
  10. ¿Qué es el análisis de flujo de datos (taint)?
  11. ¿Funciona el escaneo de flujo de datos dentro de los agentes de codificación con IA?

Seguimiento de taint por dataflow en Rust: la entrada no confiable fluye desde una fuente Query hasta un sink SQL de sqlx pasando por format! y QueryBuilder, justo donde los escáneres por patrones dejan de mirar.

Rust en producción mueve internet hoy, y la mayoría de las herramientas de análisis estático lo siguen tratando como una casilla que marcar. Añadieron *.rs al patrón de archivos, publicaron una lista de nombres de funciones peligrosas y lo llamaron compatibilidad con Rust. El trabajo real, seguir la entrada no confiable a través de funciones asíncronas, conexiones de base de datos genéricas y ayudantes derivados por macros hasta que alcanza una consulta SQL o una respuesta HTML, quedó sin hacer. Ahí es exactamente donde viven las vulnerabilidades. Por esto la coincidencia de patrones falla en Rust, y esto es lo que el análisis de flujo de datos (dataflow) detecta en su lugar.

Por qué Rust merece un escaneo de seguridad real

Rust dejó de ser una curiosidad solo para sistemas hace años. Cloudflare sirve una gran parte de la web a través de Pingora. Discord reescribió servicios críticos en rendimiento en él. AWS publica Firecracker y Bottlerocket en Rust, Stripe lo ejecuta en rutas de pago, y la lista (Linkerd, Polkadot, Solana, Tauri) crece cada mes. Este es código que maneja entrada no confiable, dinero y credenciales a escala.

El mercado de análisis estático respondió en su mayoría añadiendo Rust a un patrón de archivos y siguiendo adelante. El resultado son herramientas que o bien inundan a los equipos con falsos positivos en líneas que son obviamente seguras, o silenciosamente omiten las líneas que no lo son. En cualquier caso el informe deja de ser confiable, el escáner se desactiva en CI, y el lenguaje que se suponía más seguro termina con menos cobertura de seguridad que el servicio de JavaScript que tiene al lado. La seguridad de memoria no es seguridad de aplicación: el verificador de préstamos (borrow checker) no te impedirá concatenar entrada de usuario en una cadena SQL.

Por qué la mayoría del SAST para Rust es teatro de coincidencia de patrones

El análisis estático sobre Rust es genuinamente difícil, por razones que no aparecen en el marketing de los proveedores. Un escáner que solo coincide patrones de texto choca contra cinco muros a la vez.

Apila todo esto y Rust se convierte en un lenguaje donde la coincidencia de patrones es ruidosa donde debería callar y silenciosa donde debería gritar. La solución no son más patrones. Es el flujo de datos (dataflow).

Flujo de datos frente a coincidencia de patrones, en un ejemplo

Aquí está el tipo de error que separa los dos enfoques. Usa sqlx, el valor asíncrono moderno por defecto, y su QueryBuilder.

use sqlx::{PgPool, QueryBuilder, Postgres};

pub async fn search(pool: &PgPool, input: SearchInput) -> Result<Vec<Item>, sqlx::Error> {
    let mut q: QueryBuilder<Postgres> =
        QueryBuilder::new("SELECT * FROM items WHERE 1 = 1");

    if let Some(name) = input.name {
        // .push_bind() is safe (parameterized). .push() is concatenation.
        // This is direct SQL injection.
        q.push(" AND name LIKE '%").push(&name).push("%'");
    }

    q.build_query_as::<Item>().fetch_all(pool).await
}

Un escáner de patrones que busca format! junto a sqlx::query no encuentra nada aquí. No hay format!, ni operador de concatenación de cadenas, ni sumidero obvio. La contaminación fluye a través de QueryBuilder::push, una función que es perfectamente segura con una cadena constante y peligrosa con entrada de usuario. El escáner no puede notar la diferencia porque no sigue el valor, así que entrega un informe limpio sobre un archivo con una inyección SQL real.

Un motor de flujo de datos rastrea la contaminación desde input.name (deserializada de la petición por serde y axum) a través de la llamada .push(&name), reconoce QueryBuilder::push como un sumidero de texto SQL, y la reporta con la ruta completa. La solución es un solo método:

// .push_bind() keeps the value out of the SQL text.
q.push(" AND name LIKE ").push_bind(format!("%{}%", name));

Misma forma, propiedad de seguridad completamente distinta. Solo un análisis que sigue los datos puede distinguirlos.

Qué detecta un conjunto de reglas para Rust consciente del flujo de datos

El conjunto de reglas para Rust de CybeDefend está construido sobre este modelo, con modelos de sumideros específicos por librería para que la contaminación no se pierda cuando cruza una frontera de API. Cada hallazgo viene con la ruta completa: ubicación de la fuente, cada salto intermedio y el sumidero.

4

controladores SQL rastreados: sqlx, diesel, rusqlite, tokio-postgres

3

frameworks web para XSS: actix-web, axum, rocket

4

clientes HTTP asíncronos para SSRF: reqwest, ureq, hyper, surf

  • Inyección SQL a través de los cuatro controladores principales, siguiendo la entrada de usuario por funciones asíncronas, tipos de conexión genéricos y ayudantes de consulta derivados por macros, no solo los casos obvios de format!.
  • Cross-site scripting (XSS) en los tres frameworks principales, incluyendo HTML producido a través de los motores de plantillas askama y tera, normalizado en un único modelo de sumidero de respuesta.
  • Mala configuración de CORS, como un Access-Control-Allow-Origin comodín combinado con peticiones con credenciales, o un origen reflejado desde la petición sin una lista de permitidos, detectada en el momento de la construcción.
  • Falsificación de peticiones del lado del servidor (SSRF) en clientes HTTP asíncronos, con la contaminación seguida a través de cada ayudante constructor de URL y detenida cuando hay una lista de hosts permitidos o un filtro de IP en la ruta.

El sentido de rastrear los saneadores (sanitizers) con tanto cuidado como los sumideros es que un hallazgo solo se dispara cuando la ruta peligrosa es realmente alcanzable sin protección por medio. Eso es lo que mantiene el informe lo bastante confiable como para dejarlo activado en CI.

Dentro del bucle del agente, no solo en el panel

Las reglas de Rust no son solo un informe de CI. Se empujan a tu agente de codificación con IA a través de VibeDefend, la capa que se ejecuta dentro de Claude Code, Cursor, OpenAI Codex, Windsurf y VS Code Copilot. Cuando el agente genera Rust, el conjunto de reglas ya está cargado como contexto, así que una ruta contaminada hacia uno de los sumideros anteriores se reescribe antes de que la línea sea siquiera sugerida.

npx -y @cybedefend/vibedefend@latest installDetectado: Claude Code, Cursor, CodexConjunto de reglas para Rust cargado como contextoConsulta parametrizada al primer intento
El conjunto de reglas para Rust, cargado en el agente en el momento del prompt.

Esta es la diferencia entre atrapar un error en la revisión del PR, después de que el agente haya entregado 2,000 líneas que nadie leyó de principio a fin, y nunca escribirlo en primer lugar. No detenemos el diff en la revisión. Lo detenemos en el prompt.

Preguntas frecuentes

¿Es suficiente la seguridad de memoria de Rust para prevenir vulnerabilidades?

No. El verificador de préstamos (borrow checker) de Rust previene errores de corrupción de memoria (use-after-free, desbordamientos de buffer, condiciones de carrera de datos), que es una clase grande y valiosa. No hace nada por las vulnerabilidades a nivel de aplicación. La inyección SQL, XSS, mala configuración de CORS, SSRF, control de acceso roto y deserialización insegura ocurren todos en Rust seguro, porque tienen que ver con cómo fluyen los datos no confiables a través de tu lógica, no con la memoria. Un lenguaje seguro en memoria sigue necesitando escaneo de seguridad de aplicación.

¿Puede ocurrir inyección SQL en Rust con sqlx o diesel?

Sí. Ambas librerías ofrecen APIs seguras y parametrizadas (las macros de sqlx verificadas en tiempo de compilación y .bind(), el DSL tipado de Diesel), pero ambas también exponen escotillas de escape: sqlx::query(&str) y QueryBuilder::push aceptan cadenas en tiempo de ejecución, y diesel::sql_query ejecuta SQL en bruto. En el momento en que la entrada de usuario se concatena en una de esas, tienes inyección, sin importar lo moderno que sea el controlador. Lo mismo aplica a rusqlite y tokio-postgres.

¿Por qué las herramientas de SAST para Rust producen tantos falsos positivos?

Porque la mayoría coinciden patrones sobre nombres de funciones y formas de cadenas en lugar de seguir los datos. Los tiempos de vida, las cadenas asíncronas, los genéricos, las macros derivadas y los objetos de trait de Rust ocultan la ruta de datos real, así que un escáner de patrones marca cada llamada que parece un sumidero (ahogando al equipo en ruido) u omite la regla por completo (perdiendo errores reales). El análisis de flujo de datos reduce el ruido reportando solo las rutas que son realmente alcanzables desde una fuente no confiable sin un saneador.

¿Qué es el análisis de flujo de datos (taint)?

Es un análisis que modela un programa como un grafo de valores y pregunta, para cada operación peligrosa, si la entrada no confiable puede alcanzarla sin ser saneada. Los puntos de entrada son "fuentes", las operaciones peligrosas son "sumideros" (sinks), y una ruta limpia entre ellos sin protección es un hallazgo real y explotable. A diferencia de la coincidencia de patrones, entiende que la misma función puede ser segura o insegura según qué datos la alcancen.

¿Funciona el escaneo de flujo de datos dentro de los agentes de codificación con IA?

Sí. A través de VibeDefend, el conjunto de reglas para Rust se carga en el contexto del agente en el momento del prompt, así que Claude Code, Cursor, Codex y los demás lo aplican mientras escriben en lugar de después. Si un cambio generado introdujera una ruta contaminada hacia un sumidero SQL, HTML o HTTP, el agente produce la versión segura, parametrizada o validada al primer intento, antes de que exista el diff. Para el panorama más amplio de asegurar cada agente, consulta nuestras guías de seguridad de Claude Code, Cursor, GitHub Copilot y OpenAI Codex.

En vivo · recién lanzado

Instala VibeDefend en 5 segundos.

Un comando conecta cada agente de coding de tu máquina a CybeDefend: tus reglas de negocio, tus frameworks de cumplimiento y guards que bloquean llamadas destructivas antes de que se disparen.

Instala en 5 segundosNode 18.17+
npx -y @cybedefend/vibedefend@latest install
Auto-detecta
  • Claude CodeClaude Code
  • CursorCursor
  • OpenAI CodexOpenAI Codex
  • WindsurfWindsurf
  • GitHub CopilotVS Code Copilot
Lee el README en npm