Google vient de publier le livre blanc "Secure by Design: Google’s Perspective on Memory Safety". Google envisage une transition progressive vers des langages à sécurité mémoire tels que Java, Go et Rust pour le nouveau code et les composants particulièrement à risque. Mais Google reconnait aussi qu'il faut compléter cette transition par des améliorations de la sécurité du code C++ existant, voici son point de vue sur la sécurité de la mémoire : Résumé
L'année 2022 a marqué le 50e anniversaire des vulnérabilités liées à la sécurité de la mémoire, signalées pour la première fois par Anderson. Un demi-siècle plus tard, nous sommes toujours confrontés à des bogues de sécurité de la mémoire malgré des investissements substantiels pour améliorer les langages non sécurisés.
Comme d'autres, les données et les recherches internes de Google sur les vulnérabilités montrent que les bogues de sécurité de la mémoire sont très répandus et constituent l'une des principales causes de vulnérabilités dans les bases de code non sûres pour la mémoire. Ces vulnérabilités mettent en danger les utilisateurs finaux, notre industrie et la société dans son ensemble.
Chez Google, nous avons des dizaines d'années d'expérience dans la résolution, à grande échelle, de grandes catégories de vulnérabilités qui étaient autrefois aussi répandues que les problèmes de sécurité de la mémoire. Sur la base de cette expérience, nous pensons qu'une sécurité élevée de la mémoire ne peut être obtenue qu'au moyen d'une approche "Secure-by-Design" centrée sur l'adoption globale de langages offrant des garanties rigoureuses en matière de sécurité de la mémoire. Par conséquent, nous envisageons une transition progressive vers des langages à sécurité mémoire.
Au cours des dernières décennies, Google a développé et accumulé des centaines de millions de lignes de code C++ qui sont utilisées activement et font l'objet d'un développement actif et continu. Cette très grande base de code existante pose des problèmes importants pour la transition vers la sécurité de la mémoire :
- D'une part, nous ne voyons pas de voie réaliste pour une évolution du C++ vers un langage offrant des garanties rigoureuses de sécurité de la mémoire, y compris la sécurité temporelle.
- D'autre part, une réécriture à grande échelle du code C++ existant dans un langage différent et sûr pour la mémoire semble très difficile et restera probablement irréalisable.
Cela signifie que nous allons probablement exploiter une base de code C++ très importante pendant un certain temps. Nous considérons donc qu'il est important de compléter la transition vers des langages à mémoire sécurisée pour le nouveau code et les composants particulièrement à risque par des améliorations de la sécurité du code C++ existant, dans la mesure du possible. Nous pensons que des améliorations substantielles peuvent être obtenues par une transition progressive vers un sous-ensemble de langage C++ partiellement sûr pour la mémoire, complété par des fonctions de sécurité matérielle lorsqu'elles sont disponibles.
Définition des bogues de sécurité de la mémoire
Les bogues de sécurité de la mémoire surviennent lorsqu'un programme permet l'exécution d'instructions qui lisent ou écrivent dans la mémoire, alors que le programme est dans un état où l'accès à la mémoire constitue un comportement non défini. Lorsqu'une telle instruction est accessible dans un état de programme sous contrôle adverse (par exemple, traitement d'entrées non fiables), le bogue représente souvent une vulnérabilité exploitable (dans le pire des cas, permettant l'exécution d'un code arbitraire).
Définition d'une sécurité mémoire rigoureuse
Dans ce contexte, nous considérons qu'un langage est rigoureusement sûr en mémoire s'il :
- utilise par défaut un sous-ensemble sûr bien délimité, et
- garantit qu'un code arbitraire écrit dans le sous-ensemble sûr est empêché de provoquer une violation de la sécurité spatiale, temporelle, de type ou d'initialisation.
Ceci peut être établi par toute combinaison de restrictions à la compilation et de protections à l'exécution, à condition que les mécanismes d'exécution garantissent que la violation de la sécurité ne peut pas se produire.
À quelques exceptions près, bien définies, tout le code devrait pouvoir être écrit dans le sous-ensemble sûr bien délimité.
Dans les nouveaux développements, le code potentiellement dangereux ne devrait se trouver que dans les composants/modules qui optent explicitement pour l'utilisation de constructions non sûres en dehors du sous-ensemble de langage sûr, et qui exposent une abstraction sûre dont la solidité a été examinée par des experts. Les constructions non sûres ne doivent être utilisées qu'en cas de nécessité, par exemple pour des raisons de performances critiques ou dans le code qui interagit avec des composants de bas niveau.
Lorsque l'on travaille avec du code existant dans un langage non sûr pour la mémoire, le code non sûr doit être limité aux utilisations suivantes :
- le code écrit dans un langage sûr qui fait des appels à une bibliothèque mise en œuvre par une ancienne base de code écrite dans un langage non sûr.
- l'ajouts/modifications de code à des bases de code existantes non sûres, où le code est trop profondément entremêlé pour que le développement dans un langage sûr soit pratique.
Impact des vulnérabilités liées à la sécurité de la mémoire
Les bogues de sécurité de la mémoire sont responsables de la majorité (~70%) des vulnérabilités graves dans les grandes bases de code C/C++. Voici le pourcentage de vulnérabilités dues à l'insécurité de la mémoire :
- Chrome : 70% des vulnérabilités élevées/critiques
- Android : 70% des vulnérabilités élevées/critiques
- Serveurs Google : 16 à 29 % des vulnérabilités
- Projet Zéro : 68 % des journées zéro dans la nature
- Microsoft : 70 % des vulnérabilités avec CVE
Les erreurs de sécurité de la mémoire continuent d'apparaître en tête des listes des "bogues les plus dangereux", telles que le Top 25 et le Top 10 des vulnérabilités exploitées connues du CWE. Les recherches internes de Google sur les vulnérabilités démontrent à plusieurs reprises que l'absence de sécurité de la mémoire affaiblit d'importantes limites de sécurité.
Comprendre les bogues de sécurité de la mémoire
Catégories de bogues de sécurité de la mémoire
Il peut être utile de distinguer un certain nombre de sous-classes de bogues de sécurité de la mémoire qui diffèrent par leurs solutions possibles et leur impact sur les performances et l'expérience des développeurs :
- Les bogues de sécurité spatiale (par exemple, "dépassement de tampon", "accès hors limites") surviennent lorsqu'un accès à la mémoire se réfère à une mémoire située en dehors de la région allouée à l'objet accédé.
- Les bogues de sécurité temporelle surviennent lorsqu'un accès à la mémoire d'un objet se produit en dehors de la durée de vie de l'objet. C'est le cas, par exemple, lorsqu'une fonction renvoie un pointeur sur une valeur de sa pile ("use-after-return"), ou en raison d'un pointeur sur une mémoire allouée au tas qui a depuis été libérée, et éventuellement réallouée pour un autre objet ("use-after-free").
Dans les programmes concurrents, il est courant que ces bogues se produisent en raison d'une mauvaise synchronisation des threads, mais lorsque la violation initiale de la sécurité se situe en dehors de la durée de vie de l'objet, nous la classons comme une violation de la sécurité temporelle. - Les bogues de sécurité de type surviennent lorsqu'une valeur d'un type donné est lue à partir d'une mémoire qui ne contient pas de membre de ce type. C'est le cas, par exemple, lorsque la mémoire est lue après un cast de pointeur invalide.
- Les bogues de sécurité d'initialisation surviennent lorsque la mémoire est lue avant d'être initialisée. Cela peut conduire à des divulgations d'informations et à des bogues de sécurité de type/temporels.
- Les bogues de sécurité liés à la course aux données résultent de lectures et d'écritures non synchronisées par différents threads, qui peuvent accéder à un objet dans un état incohérent. D'autres formes de bogues de sécurité peuvent également résulter d'une synchronisation incorrecte ou manquante, mais nous ne les classons pas dans la catégorie des bogues de sécurité liés à l'espace de données et ils sont traités ci-dessus. Ce n'est que lorsque les lectures et les écritures sont par ailleurs correctes, à l'exception du fait qu'elles ne sont pas synchronisées, qu'elles sont considérées comme des bogues de sécurité liés à l'évolution des données.
Une fois qu'une violation de la sécurité de l'espace de données s'est produite, l'exécution ultérieure peut provoquer d'autres bogues de sécurité. Nous les classons dans la catégorie des bogues de sécurité liés à la course aux données, car la violation initiale est strictement un problème lié à la course aux données, sans qu'aucun autre bogue ne soit évident.
La classification utilisée ici correspond à peu près à la taxonomie de sécurité de la mémoire d'Apple.
Dans les langages non sécurisés tels que C/C++, il incombe au programmeur de s'assurer que les conditions préalables de sécurité sont remplies afin d'éviter d'accéder à une mémoire non valide. Par exemple, pour la sécurité spatiale, lors de l'accès aux éléments d'un tableau via un index (par exemple, a[i] = x), il incombe au programmeur de s'assurer que l'index se trouve dans les limites de la mémoire allouée de manière valide.
Nous excluons actuellement la sécurité de la trace des données de la prise en compte de la sécurité rigoureuse de la mémoire pour les raisons suivantes :
- La sécurité de la course aux données est une classe de bogues à part entière, qui ne recouvre que partiellement la sécurité de la mémoire. Par exemple, Java ne fournit pas de garanties en matière de sécurité des courses de données, mais les courses de données en Java ne peuvent pas entraîner la violation des invariants d'intégrité du tas de données de bas niveau (corruption de la mémoire).
- À l'heure actuelle, nous ne disposons pas du même niveau de preuve concernant l'insécurité des courses de données, qui entraîne des problèmes systémiques de sécurité et de fiabilité pour les logiciels écrits dans des langages par ailleurs rigoureusement sûrs pour la mémoire (par exemple, Go).
Pourquoi les bogues de sécurité de la mémoire sont-ils si difficiles à résoudre ?
Les bogues de sécurité de la mémoire sont assez courants dans les grandes bases de code C++. L'intuition qui sous-tend la prévalence des bogues de sécurité de la mémoire est la suivante :
Premièrement, dans les langages non sûrs, les programmeurs doivent s'assurer que la condition préalable de sécurité de la mémoire de chaque instruction est remplie juste avant son exécution, dans n'importe quel état du programme qui pourrait être atteint, potentiellement sous l'influence d'entrées adverses dans le programme.
Deuxièmement, les instructions non sûres qui peuvent entraîner des bogues de sécurité de la mémoire sont très courantes dans les programmes C/C++ - il y a beaucoup d'accès aux tableaux, de déréférencements de pointeurs et d'allocations du tas.
Enfin, il est difficile, même avec l'aide d'un outil, de raisonner sur les conditions préalables de sécurité et de déterminer si le programme les garantit dans tous les états possibles du programme. Par exemple :
- Raisonner sur l'intégrité d'un pointeur/index implique d'envelopper l'arithmétique des entiers, ce qui est tout à fait non intuitif pour les humains.
- Le raisonnement sur la durée de vie des objets du tas implique souvent des invariants complexes et subtils pour l'ensemble du programme. Même le cadrage local et la durée de vie peuvent être subtils et surprenants.
"De nombreux bogues potentiels" combinés à un "raisonnement difficile sur les conditions préalables de sécurité" et au fait que "les humains font des erreurs" se traduisent par un nombre relativement important de bogues réels.
Les tentatives d'atténuation du risque de vulnérabilité de la mémoire par l'éducation des développeurs et des approches réactives (y compris l'analyse statique/dynamique pour trouver et corriger les bogues, et diverses mesures d'atténuation des exploits) n'ont pas réussi à réduire l'incidence de ces bogues à un niveau tolérable. En conséquence, des vulnérabilités graves continuent d'être causées par cette catégorie de failles, comme nous l'avons vu plus haut.
S'attaquer aux bogues de sécurité de la mémoire
S'attaquer à la sécurité de la mémoire nécessite une approche sur plusieurs fronts :
- Prévenir les bogues de sécurité de la mémoire par un codage sûr.
- Atténuer les bogues de sécurité de la mémoire en rendant leur exploitation plus coûteuse.
- Détecter les bogues de sécurité de la mémoire, le plus tôt possible dans le cycle de développement.
Nous pensons que ces trois éléments sont nécessaires pour résoudre le problème de la sécurité de la mémoire à l'échelle de Google. D'après notre expérience, il est nécessaire de mettre l'accent sur la prévention par le biais d'un codage sûr pour atteindre durablement un niveau d'assurance élevé.
Prévention des bogues de sécurité de la mémoire par un codage sûr
Notre expérience chez Google montre qu'il est possible d'éliminer des classes de problèmes à grande échelle en supprimant l'utilisation de constructions de codage sujettes à la vulnérabilité. Dans ce contexte, nous considérons qu'une construction n'est pas sûre si elle peut potentiellement manifester un bogue (par exemple, une corruption de la mémoire) à moins qu'une condition préalable de sécurité ne soit satisfaite au moment de son utilisation. Les constructions non sûres mettent à la charge du développeur la responsabilité de garantir la condition préalable. Notre approche, que nous appelons "Safe Coding", traite les constructions de codage non sûres elles-mêmes comme des dangers (c'est-à-dire indépendamment et en plus de la vulnérabilité qu'ils peuvent causer), et est centrée sur l'assurance que les développeurs ne rencontrent pas de tels dangers lors de la pratique régulière du codage.
En substance, le codage sûr demande que les constructions dangereuses soient interdites par défaut et que leur utilisation soit remplacée par des abstractions sûres dans la plupart des codes, avec des exceptions soigneusement examinées. Dans le domaine de la sécurité de la mémoire, les abstractions sûres peuvent être fournies en utilisant :
- Des invariants de sécurité garantis statiquement ou dynamiquement, empêchant l'introduction de bogues. Des vérifications au moment de la compilation et des mécanismes émis par le compilateur ou fournis au moment de l'exécution garantissent que des classes particulières de bogues ne peuvent pas se produire. Par exemple, au moment de la compilation, l'analyse de la durée de vie empêche les bogues de se produire :
- Au moment de la compilation, l'analyse de la durée de vie empêche un sous-ensemble de bogues de sécurité temporelle.
- Au moment de l'exécution, l'initialisation automatisée des objets garantit l'absence de lectures non initialisées.
- Détection d'erreurs au moment de l'exécution, application des invariants de sécurité de la mémoire en levant une erreur lorsqu'une violation de la sécurité de la mémoire est détectée au lieu de poursuivre l'exécution avec une mémoire corrompue. Les bogues sous-jacents existent toujours et devront être corrigés, mais les vulnérabilités sont éliminées (à l'exception des attaques par déni de service). Par exemple :
- Une recherche dans un tableau peut offrir une détection d'erreur de sécurité spatiale en vérifiant que l'index donné est à l'intérieur des limites. Les vérifications peuvent être supprimées lorsque la sécurité est prouvée de manière statique.
- Un cast de type peut offrir une détection d'erreur de sécurité de type en vérifiant que l'objet casté est une instance du type résultant (par exemple, ClassCastException en Java ou CastGuard pour C++).
Dans le domaine de la sécurité de la mémoire, l'approche du codage sûr est incarnée par des langages sûrs, qui remplacent les constructions non sûres par des abstractions sûres telles que les vérifications des limites d'exécution, les références collectées par le garbage, ou les références ornées d'annotations de durée de vie vérifiées de manière statique.
L'expérience montre que les problèmes de sécurité de la mémoire sont en effet rares dans les langages sûrs à ramasse-miettes tels que Go et Java. Cependant, le ramassage des ordures s'accompagne généralement d'un surcoût d'exécution important. Plus récemment, Rust est apparu comme un langage qui incarne l'approche du codage sûr basée principalement sur la discipline de type vérifiée à la compilation, ce qui entraîne des surcoûts d'exécution minimes.
Les données montrent que le codage sécurisé fonctionne pour la sécurité de la mémoire, même dans les environnements sensibles aux performances. Par exemple, Android 13 a introduit 1,5 million de lignes de Rust sans aucune vulnérabilité en matière de sécurité de la mémoire. Cela a permis d'éviter des centaines de vulnérabilités en matière de sécurité de la mémoire : "La quantité de nouveau code dangereux pour la mémoire entrant dans Android a diminué, tout comme le nombre de vulnérabilités en matière de sécurité de la mémoire. [...] 2022 a été la première année où les vulnérabilités liées à la sécurité de la mémoire n'ont pas représenté la majorité des vulnérabilités d'Android. Bien que la corrélation ne signifie pas nécessairement la causalité, [...] le changement est un écart majeur par rapport aux tendances de l'ensemble de l'industrie énumérées ci-dessus qui ont persisté pendant plus d'une décennie".
Autre exemple, Cloudflare indique que son proxy HTTP Rust est plus performant que NGINX et qu'il a "servi quelques centaines de milliers de milliards de requêtes et [n'a] encore jamais connu de panne due à notre code de service".
En appliquant un sous-ensemble de mécanismes préventifs de sécurité de la mémoire à un langage non sûr tel que le C++, nous pouvons partiellement prévenir des classes de problèmes de sécurité de la mémoire. Par exemple :
- Un RFC de renforcement des tampons peut éliminer un sous-ensemble de problèmes de sécurité spatiale en C++.
- De même, un RFC sur la sécurité des limites peut éliminer un sous-ensemble de problèmes de sécurité spatiale en C.
- Les annotations de durée de vie en C++ peuvent éliminer un sous-ensemble de problèmes de sécurité temporelle.
Atténuation des risques d'exploitation
Les mesures d'atténuation compliquent l'exploitation des vulnérabilités de la sécurité de la mémoire, plutôt que de corriger la cause première de ces vulnérabilités. Par exemple, les mesures d'atténuation comprennent la mise en bac à sable des bibliothèques non sûres, l'intégrité du flux de contrôle et la prévention de l'exécution des données.
Alors que les abstractions sûres empêchent la corruption de la mémoire, refusant aux attaquants les primitives d'exploitation, les mesures d'atténuation des exploits supposent que la mémoire peut être corrompue. Les mesures d'atténuation des risques visent à empêcher les attaquants de passer de certaines primitives d'exploitation à l'exécution de code sans restriction.
Les attaquants contournent régulièrement ces mesures d'atténuation, ce qui soulève la question de leur valeur en termes de sécurité. Pour être utiles, les mesures d'atténuation devraient obliger les attaquants à enchaîner des vulnérabilités supplémentaires ou à inventer une nouvelle technique de contournement. Au fil du temps, les techniques de contournement deviennent plus précieuses pour les attaquants que n'importe quelle vulnérabilité isolée. L'avantage pour la sécurité d'une
d'une atténuation bien conçue réside dans le fait que les techniques de contournement devraient être beaucoup plus rares que les vulnérabilités.
Les mesures d'atténuation des exploits sont rarement gratuites ; elles ont tendance à entraîner des frais généraux d'exécution qui ne représentent généralement qu'un faible pourcentage à un chiffre.
Elles offrent un compromis entre sécurité et performance, que nous pouvons ajuster en fonction des besoins de chaque charge de travail. Les frais généraux d'exécution peuvent être réduits en construisant des mesures d'atténuation directement dans le silicium, comme cela a été fait pour l'authentification des pointeurs, la pile d'appels fictifs, les plateformes d'atterrissage et les clés de protection. En raison des frais généraux et des coûts d'opportunité des caractéristiques matérielles, les considérations relatives à l'adoption de ces techniques et à l'investissement dans celles-ci sont nuancées.
D'après notre expérience, le sandboxing est un moyen efficace d'atténuer les vulnérabilités liées à la sécurité de la mémoire et il est couramment utilisé chez Google pour isoler les bibliothèques fragiles ayant un historique de vulnérabilités. Toutefois, l'adoption du sandboxing se heurte à plusieurs obstacles :
- Le sandboxing peut entraîner des frais généraux importants en termes de latence et de bande passante, ainsi que des coûts liés au remaniement du code. Cela nécessite parfois la réutilisation des instances de sandbox entre les requêtes, ce qui affaiblit les mesures d'atténuation.
- La création d'une politique de sandbox suffisamment restrictive pour constituer une mesure d'atténuation efficace peut s'avérer difficile pour les développeurs, en particulier lorsque les politiques de sandbox sont exprimées à un faible niveau d'abstraction, comme les filtres d'appels système.
- Le sandboxing peut entraîner des risques de fiabilité, lorsque des chemins de code inhabituels (mais bénins) sont exercés en production et déclenchent des violations de la politique de sandboxing.
Dans l'ensemble, l'atténuation des exploits est un outil essentiel pour améliorer la sécurité d'une vaste base de code C++ préexistante et profitera également à l'utilisation résiduelle de constructions non sûres dans des langages à mémoire sûre.
Détection des bogues liés à la sécurité de la mémoire
L'analyse statique et le fuzzing sont des outils efficaces pour détecter les bogues de sécurité de la mémoire. Ils réduisent le volume de bogues de sécurité de la mémoire dans notre base de code au fur et à mesure que les développeurs corrigent les problèmes détectés.
Cependant, d'après notre expérience, la recherche de bogues ne permet pas à elle seule d'atteindre un niveau d'assurance acceptable pour les langages à mémoire non sécurisée. À titre d'exemple, le récent zero-day de haute sévérité de webp (CVE-2023-4863) a affecté un code largement exploré. La vulnérabilité n'a pas été détectée malgré une couverture élevée (97,55 % dans le fichier concerné). Dans la pratique, de nombreux bogues liés à la sécurité de la mémoire ne sont pas détectés, comme le montre le flux constant de vulnérabilités liées à la sécurité de la mémoire dans un code bien testé qui n'est pas sûr pour la mémoire.
En outre, le fait de trouver des bogues n'améliore pas en soi la sécurité. Les bogues doivent être corrigés et les correctifs déployés. Certains éléments suggèrent que les capacités de détection des bogues dépassent les capacités de correction des bogues. Par exemple, syzkaller, notre fuzzer de noyau, a trouvé plus de 5 000 bogues dans le noyau Linux en amont, de sorte qu'à tout moment, il y a des centaines de bogues ouverts (dont une grande partie est probablement liée à la sécurité), un nombre qui augmente régulièrement depuis 2017.
Nous pensons néanmoins que la recherche de bogues est une partie essentielle de la lutte contre l'insécurité de la mémoire. Les techniques de recherche de bogues qui exercent une pression moindre sur la capacité de correction des bogues sont particulièrement précieuses :
- " Shifting-left ", comme le fuzzing en presubmit, réduit le taux de nouveaux bugs expédiés en production. Les bogues détectés plus tôt dans le cycle de développement des logiciels (SDLC) sont moins coûteux à corriger, ce qui augmente notre capacité de correction des bogues.
- Les techniques de recherche de bogues, comme l'analyse statique, peuvent également suggérer des corrections, qui peuvent être fournies par l'intermédiaire de l'IDE ou de demandes d'extraction, ou appliquées automatiquement pour modifier le code existant de manière proactive.
- Les outils de recherche de bogues tels que les assainisseurs, qui identifient les causes profondes et génèrent des rapports de bogues exploitables, aident les développeurs à résoudre les problèmes plus rapidement, ce qui augmente également notre capacité de correction des bogues.
En outre, les outils de recherche de bogues trouvent des classes de bogues au-delà de la sécurité de la mémoire, ce qui élargit l'impact de l'investissement dans ces outils. Ils peuvent trouver des problèmes de fiabilité, de correction et d'autres problèmes de sécurité, par exemple :
- Le fuzzing basé sur les propriétés détecte les entrées qui violent les invariants au niveau de l'application, tels que les propriétés de correction encodées par les développeurs. Par exemple, cryptofuzz a trouvé plus de 150 bogues dans les bibliothèques de cryptographie.
- Le fuzzing détecte les bogues liés à l'utilisation des ressources (par exemple, les récursions infinies) et les pannes simples qui affectent la disponibilité. En particulier, la détection des erreurs d'exécution (par exemple, la vérification des limites) transforme les vulnérabilités de sécurité de la mémoire en erreurs d'exécution, qui restent un problème de fiabilité et de déni de service.
- Les progrès dans la détection des vulnérabilités au-delà de la sécurité de la mémoire sont prometteurs.
Plongée en profondeur : Safe Coding appliqué à la sécurité de la mémoire
Google a développé Safe Coding, une approche évolutive visant à réduire considérablement l'incidence des classes communes de vulnérabilités et à obtenir un degré élevé d'assurance quant à l'absence de vulnérabilités.
Au cours de la dernière décennie, nous avons appliqué cette approche avec beaucoup de succès à l'échelle de Google, principalement pour ce que l'on appelle les vulnérabilités d'injection, y compris l'injection SQL et XSS. Bien qu'à un niveau technique très différent des bogues de sécurité de la mémoire, il existe des parallèles pertinents :
- Comme les bogues de sécurité de la mémoire, les bogues d'injection se produisent lorsqu'un développeur utilise une construction de code potentiellement dangereuse et ne parvient pas à garantir sa condition préalable de sécurité.
- Le respect de la condition préalable dépend d'un raisonnement complexe sur les invariants de flux de données de l'ensemble du programme ou de l'ensemble du système. Par exemple, la construction potentiellement dangereuse se produit dans le code côté navigateur, mais les données peuvent arriver via plusieurs microservices et un magasin de données côté serveur. Il est donc difficile de savoir d'où viennent réellement les données et si la validation nécessaire a été correctement appliquée en cours de route.
- Les constructions potentiellement dangereuses sont courantes dans les bases de code typiques.
Comme pour les bogues liés à la sécurité de la mémoire, "plusieurs milliers de bogues potentiels" ont conduit à des centaines de bogues réels. Les approches réactives (examen du code, tests en stylo, fuzzing) ont été largement infructueuses.
Pour résoudre ce problème à grande échelle et avec une grande assurance, Google a appliqué le Safe Coding au domaine des...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.