Sur cette page
- Pourquoi Rust mérite une vraie analyse de sécurité
- Pourquoi la plupart du SAST Rust n'est qu'un théâtre de correspondance de motifs
- Flux de données contre correspondance de motifs, en un seul exemple
- Ce que détecte un ruleset Rust conscient du flux de données
- Dans la boucle de l'agent, pas seulement le dashboard
- Foire aux questions
- La sûreté mémoire de Rust suffit-elle à prévenir les vulnérabilités ?
- Une injection SQL peut-elle se produire en Rust avec sqlx ou diesel ?
- Pourquoi les outils de SAST Rust produisent-ils autant de faux positifs ?
- Qu'est-ce que l'analyse de flux de données (taint analysis) ?
- L'analyse de flux de données fonctionne-t-elle dans les agents de codage IA ?

Rust en production fait désormais tourner Internet, et la plupart des outils d'analyse statique le traitent encore comme une case à cocher. Ils ont ajouté *.rs au filtre de fichiers, livré une liste de noms de fonctions dangereuses et appelé ça du support Rust. Le vrai travail, suivre une entrée non fiable à travers des fonctions asynchrones, des connexions de base de données génériques et des helpers dérivés par macro jusqu'à ce qu'elle atteigne une requête SQL ou une réponse HTML, est resté inachevé. C'est exactement là que vivent les vulnérabilités. Voici pourquoi la correspondance de motifs échoue sur Rust, et ce que l'analyse de flux de données (dataflow) détecte à la place.
Pourquoi Rust mérite une vraie analyse de sécurité
Rust a cessé d'être une curiosité réservée aux systèmes il y a des années. Cloudflare sert une large part du web via Pingora. Discord a réécrit ses services critiques en performance avec. AWS livre Firecracker et Bottlerocket en Rust, Stripe l'exécute sur ses chemins de paiement, et la liste (Linkerd, Polkadot, Solana, Tauri) s'allonge chaque mois. C'est du code qui manipule des entrées non fiables, de l'argent et des identifiants à grande échelle.
Le marché de l'analyse statique a surtout répondu en ajoutant Rust à un filtre et en passant à autre chose. Le résultat, c'est un outillage qui soit noie les équipes sous les faux positifs sur des lignes manifestement sûres, soit manque discrètement celles qui ne le sont pas. Dans les deux cas le rapport cesse d'être crédible, le scanner est désactivé en CI, et le langage censé être plus sûr finit avec moins de couverture de sécurité que le service JavaScript juste à côté. La sûreté mémoire n'est pas la sécurité applicative : le borrow checker ne vous empêchera pas de concaténer une entrée utilisateur dans une chaîne SQL.
Pourquoi la plupart du SAST Rust n'est qu'un théâtre de correspondance de motifs
L'analyse statique sur Rust est réellement difficile, pour des raisons qui n'apparaissent pas dans le marketing des éditeurs. Un scanner qui ne fait que matcher des motifs textuels se heurte à cinq murs d'un coup.
Empilez tout ça et Rust devient un langage où la correspondance de motifs est bruyante là où elle devrait être silencieuse et silencieuse là où elle devrait être bruyante. La solution n'est pas plus de motifs. C'est le flux de données (dataflow).
Flux de données contre correspondance de motifs, en un seul exemple
Voici le type de bug qui sépare les deux approches. Il utilise sqlx, le défaut asynchrone moderne, et son 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 scanner par motifs qui cherche format! à côté de sqlx::query ne trouve rien ici. Pas de format!, pas d'opérateur de concaténation de chaînes, pas de puits évident. La teinte circule à travers QueryBuilder::push, une fonction parfaitement sûre avec une chaîne constante et dangereuse avec une entrée utilisateur. Le scanner ne peut pas faire la différence parce qu'il ne suit pas la valeur, alors il livre un rapport propre sur un fichier contenant une vraie injection SQL.
Un moteur de flux de données trace la teinte depuis input.name (désérialisée depuis la requête par serde et axum) à travers l'appel .push(&name), reconnaît QueryBuilder::push comme un puits de texte SQL, et le rapporte avec le chemin complet. Le correctif tient en une seule méthode :
// .push_bind() keeps the value out of the SQL text.
q.push(" AND name LIKE ").push_bind(format!("%{}%", name));
Même forme, propriété de sécurité totalement différente. Seule une analyse qui suit les données peut les distinguer.
Ce que détecte un ruleset Rust conscient du flux de données
Le ruleset Rust de CybeDefend est bâti sur ce modèle, avec des modèles de puits spécifiques à chaque bibliothèque pour que la teinte ne soit pas perdue quand elle franchit une frontière d'API. Chaque finding est livré avec le chemin complet : emplacement de la source, chaque saut intermédiaire et le puits.
pilotes SQL suivis : sqlx, diesel, rusqlite, tokio-postgres
frameworks web pour le XSS : actix-web, axum, rocket
clients HTTP asynchrones pour le SSRF : reqwest, ureq, hyper, surf
- Injection SQL à travers les quatre pilotes majeurs, en suivant l'entrée utilisateur à travers les fonctions asynchrones, les types de connexion génériques et les helpers de requête dérivés par macro, pas seulement les cas évidents en
format!. - Cross-site scripting (XSS) sur les trois frameworks grand public, y compris le HTML produit par les moteurs de templates
askamaettera, normalisé en un seul modèle de puits de réponse. - Mauvaise configuration CORS, comme un
Access-Control-Allow-Originen wildcard combiné à des requêtes avec identifiants, ou une origine reflétée depuis la requête sans liste d'autorisation, détectée au moment de la construction. - Server-side request forgery (SSRF) dans les clients HTTP asynchrones, avec la teinte suivie à travers chaque helper de construction d'URL et stoppée quand une liste d'autorisation d'hôtes ou un filtre d'IP est présent sur le chemin.
L'intérêt de suivre les assainisseurs (sanitizers) aussi soigneusement que les puits, c'est qu'un finding ne se déclenche que lorsque le chemin dangereux est réellement atteignable sans aucune protection entre les deux. C'est ce qui garde le rapport assez crédible pour le laisser actif en CI.
Dans la boucle de l'agent, pas seulement le dashboard
Les règles Rust ne sont pas qu'un rapport CI. Elles sont poussées dans votre agent de codage IA via VibeDefend, la couche qui s'exécute dans Claude Code, Cursor, OpenAI Codex, Windsurf et VS Code Copilot. Quand l'agent génère du Rust, le ruleset est déjà chargé en contexte, donc un chemin teinté vers l'un des puits ci-dessus est réécrit avant même que la ligne ne vous soit suggérée.
C'est la différence entre attraper un bug à la revue de pull request, après que l'agent a livré 2 000 lignes que personne n'a lues de bout en bout, et ne jamais l'écrire en premier lieu. Nous n'arrêtons pas le diff à la revue. Nous l'arrêtons au prompt.
Foire aux questions
La sûreté mémoire de Rust suffit-elle à prévenir les vulnérabilités ?
Non. Le borrow checker de Rust prévient les bugs de corruption mémoire (use-after-free, débordements de tampon, data races), une classe vaste et précieuse. Il ne fait rien contre les vulnérabilités applicatives. Injection SQL, XSS, mauvaise configuration CORS, SSRF, contrôle d'accès cassé et désérialisation non sécurisée surviennent tous dans du Rust sûr, parce qu'ils concernent la façon dont les données non fiables circulent à travers votre logique, pas la mémoire. Un langage à sûreté mémoire a quand même besoin d'une analyse de sécurité applicative.
Une injection SQL peut-elle se produire en Rust avec sqlx ou diesel ?
Oui. Les deux bibliothèques offrent des API sûres et paramétrées (les macros vérifiées à la compilation et .bind() de sqlx, le DSL typé de Diesel), mais les deux exposent aussi des échappatoires : sqlx::query(&str) et QueryBuilder::push prennent des chaînes à l'exécution, et diesel::sql_query exécute du SQL brut. Dès qu'une entrée utilisateur est concaténée dans l'une d'elles, vous avez une injection, quelle que soit la modernité du pilote. La même chose vaut pour rusqlite et tokio-postgres.
Pourquoi les outils de SAST Rust produisent-ils autant de faux positifs ?
Parce que la plupart matchent des noms de fonctions et des formes de chaînes au lieu de suivre les données. Les durées de vie, chaînes asynchrones, génériques, macros dérivées et objets-traits de Rust cachent le vrai chemin de données, donc un scanner par motifs signale chaque appel qui ressemble à un puits (noyant l'équipe sous le bruit) ou saute carrément la règle (manquant de vrais bugs). L'analyse de flux de données réduit le bruit en ne rapportant que les chemins réellement atteignables depuis une source non fiable sans aucun assainisseur.
Qu'est-ce que l'analyse de flux de données (taint analysis) ?
C'est une analyse qui modélise un programme comme un graphe de valeurs et demande, pour chaque opération dangereuse, si une entrée non fiable peut l'atteindre sans être assainie. Les points d'entrée sont des « sources », les opérations dangereuses sont des « puits » (sinks), et un chemin propre entre eux sans protection est un finding réel et exploitable. Contrairement à la correspondance de motifs, elle comprend que la même fonction peut être sûre ou dangereuse selon les données qui l'atteignent.
L'analyse de flux de données fonctionne-t-elle dans les agents de codage IA ?
Oui. Via VibeDefend, le ruleset Rust est chargé dans le contexte de l'agent au moment du prompt, donc Claude Code, Cursor, Codex et les autres l'appliquent pendant qu'ils écrivent plutôt qu'après. Si un changement généré introduisait un chemin teinté vers un puits SQL, HTML ou HTTP, l'agent produit la version sûre, paramétrée ou validée du premier coup, avant que le diff n'existe. Pour une vue d'ensemble de la sécurisation de chaque agent, voyez nos guides sur la sécurité de Claude Code, Cursor, GitHub Copilot et OpenAI Codex.


