
Cet article est le fruit d'une collaboration entre Consensys Diligence et le projet MSQ, avec le soutien de la DFinity Foundation et du MetaMask Snaps DAO

Consensys Diligence est une branche d'audit au sein de Consensys Software Inc., reconnue pour son expertise inégalée dans la conduite d'audits minutieux couvrant un spectre allant de Solidity et Cairo à un ensemble de bibliothèques ZK. L'équipe Diligence est à l'avant-garde des normes d'audit et de sécurité pour MetaMask Snaps et travaille en étroite collaboration avec l'équipe MetaMask pour garantir la sécurité des fonctionnalités du portefeuille. De plus, l'équipe Diligence est pionnière dans le développement d'outils de sécurité et de solutions de fuzzing continu de pointe, validées dans les environnements de production les plus exigeants.
Le projet MSQ a récemment été lancé sur le MetaMask Snaps Store. MSQ est un Snap qui permet aux utilisateurs d'interagir avec le réseau Internet Computer, de gérer des tokens basés sur IC, d'autoriser en toute sécurité au sein des dapps basées sur IC, et de payer des biens et services numériques. En substance, il s'agit d'un portefeuille crypto intégré à MetaMask, conçu spécifiquement pour l'Internet Computer avec des fonctionnalités distinctes pour l'autorisation et les paiements.
Ensemble, les équipes Diligence et MSQ ont identifié cinq domaines clés à aborder dans cet article — Documentation, Conception logicielle, Code, Chaîne d'approvisionnement et Corrections — en fournissant une liste de pratiques employées par l'équipe MSQ lors du développement, accompagnée de commentaires de l'équipe Diligence détaillant les avantages de sécurité de ces pratiques. Cela en fait une ressource utile pour toute personne développant un Snap pour MetaMask Wallet ou tout autre système critique en matière de sécurité susceptible de faire l'objet d'un audit de sécurité. Commençons !
La documentation transforme les concepts dans votre tête en quelque chose de visible pour les autres. Une documentation en couches aide le lecteur à comprendre ces concepts de la manière que vous souhaitez, en l'immergeant progressivement dans le contexte. Évidemment, plus la documentation est claire, plus elle offre une perspective large sur votre projet, et mieux les autres vous comprendront.
Nous définissons les couches de documentation dans l'ordre inverse de la façon dont un lecteur y accéderait normalement, chaque couche offrant un niveau d'abstraction plus élevé. Ainsi, les lecteurs qui commencent par la vue d'ensemble plongeront progressivement dans les détails.
La source d'information ultime sur votre logiciel est le code lui-même, qui constitue la couche fondamentale de votre documentation. Bien qu'il contienne toutes les informations nécessaires, il est difficile de les traiter. Plus le code est propre, plus il est facile d'en extraire les abstractions de haut niveau. Mais dans les systèmes réels, ces abstractions sont cachées derrière des interactions complexes entre les composants du système, des semaines de dette technique et des solutions rapides et approximatives.
Ainsi, avant tout, vous souhaitez protéger les personnes qui lisent votre code contre toute confusion causée par des parties complexes de votre système. La meilleure façon d'y parvenir est de réduire la charge cognitive nécessaire à la lecture de votre code. Voici quelques stratégies :
Rendre votre code navigable, permettant une traversée facile dans les IDE.
Utiliser des noms explicites pour clarifier le but et la fonctionnalité des éléments de code.
Employer des langages fortement typés pour définir des formats de données clairs.
Le Snap MSQ et les frontends de la dapp sont développés en TypeScript, ce qui a permis d'éviter de nombreuses erreurs potentielles, contrairement aux pièges du JavaScript ordinaire. De même, notre backend s'appuie sur Rust, connu pour son système de types robuste. De plus, MSQ Snap exporte un ensemble de méthodes pouvant être exécutées par une application tierce. Cependant, nous n'utilisons pas de chaînes de caractères pour identifier ces méthodes, mais des constantes. Nous avons un objet constant comme celui-ci :
Dans le code, cet objet constant peut servir de guide pour accéder à la bonne méthode, et les lecteurs peuvent comprendre beaucoup sur cette méthode grâce à son identifiant dans l'objet. Par exemple, la méthode SNAP_METHODS.protected.identity.login ne peut être exécutée que par la dapp compagnon de MSQ et permet à l'utilisateur de se connecter. Cette approche améliore la clarté du code et simplifie le refactoring, car les modifications des noms de méthodes sont gérées de manière centralisée plutôt que mises à jour dans plusieurs occurrences.
Pour faire correspondre les noms de méthodes, nous utilisons une grande expression switch avec des branches comme celle-ci :
Comme vous pouvez le constater, il est très difficile de mal interpréter quoi que ce soit en lisant ce code — tout est nommé avec précision, ne laissant aucune place à l'imagination.
Commentaire Diligence Le temps est un facteur critique. Alors que les développeurs ont des semaines pour comprendre une base de code, les ingénieurs en sécurité n'ont souvent que quelques jours pour identifier les risques. Cette contrainte souligne l'importance de réduire la charge cognitive dans le code — une pratique qui profite à la fois à l'efficacité des développeurs et à la sécurité.
Ce que nous pouvons apprendre de la base de code de MSQ, c'est qu'un code clair et navigable avec des noms descriptifs et un typage fort (comme TypeScript) réduit les malentendus, source fréquente de vulnérabilités.
Mais n'oubliez pas que les annotations de type TypeScript ne sont vérifiées qu'à la compilation ! Pour toute donnée traitée ou analysée à l'exécution (RPC, JSON, ...), des vérifications supplémentaires de type, de format de données et de limites sont nécessaires ! À cette fin, MSQ utilise élégamment zod, une bibliothèque de validation de schéma TypeScript-first avec inférence de type statique, et nous recommandons aux équipes de suivre cette approche.
MSQ a trouvé le juste équilibre en rendant les intentions du code claires grâce à une quantité appropriée de commentaires. Cette clarté aide les chercheurs en sécurité à saisir rapidement le « fil conducteur » et les concepts fondamentaux de la base de code. En écrivant du code facile à comprendre, les développeurs améliorent considérablement l'efficacité des revues de sécurité rapides.
Nous pensons que commenter ne consiste pas à couvrir 100 % de votre code. Il est essentiel d'annoter les parties complexes ou mal écrites. Les zones telles que les expressions régulières, la cryptographie et les manipulations de chaînes bénéficient particulièrement de commentaires clairs.
Par exemple, chez MSQ, nous avons une fonction qui échappe les caractères de contrôle Markdown possibles dans une chaîne. Son corps est une seule ligne de code, mais il y a une correspondance d'expression régulière, donc nous décrivons sa fonctionnalité dans un commentaire :
Si vous n'avez pas d'objection à l'IA dans votre flux de travail, ChatGPT est excellent pour générer rapidement de bons commentaires pour de telles fonctions utilitaires (vérifiez simplement le résultat qu'il fournit).
Commentaire Diligence En tant que réviseurs de sécurité, nous utilisons les commentaires de fonctions comme des feuilles de route à travers du code inconnu. N'oubliez pas que nous disposons d'un temps limité pour réviser le code, et lorsque les commentaires ne correspondent pas à l'implémentation, ce n'est pas seulement déroutant — c'est un signal d'alarme.
Ils révèlent souvent que la fonction ou sa description s'écarte des spécifications, signalant des vulnérabilités potentielles. Peut-être qu'une fonction ignore des vérifications promises ou traite les données de manière inattendue, ce qui peut avoir de graves conséquences.
Par conséquent, gardez vos commentaires concis et précis, comme MSQ le fait dans sa base de code. Les commentaires en ligne ne sont pas de simples notes ; ce sont des balises qui nous guident à travers votre code, et les incohérences sont des indices que quelque chose pourrait ne pas aller.
Après vous être assuré que votre code et ses complexités sont bien documentés, l'étape suivante consiste à décrire l'architecture du système. Cela implique de détailler les interactions entre les composants, ainsi que les protocoles, algorithmes et structures de données utilisés par votre logiciel. Cette couche utilise principalement des formats lisibles par l'homme, tels que du texte et des diagrammes, plutôt que du code.
La documentation système de MSQ comprend une vue d'ensemble de l'architecture et un guide d'intégration. Ces documents, riches en descriptions textuelles, exemples et diagrammes, clarifient la façon dont les différentes parties du système interagissent.
Les diagrammes de séquence sont précieux pour visualiser les interactions entre composants. Nous recommandons d'utiliser diagrams.net (draw.io), un outil gratuit qui s'est révélé polyvalent dans divers projets.
Commentaire Diligence Contrairement aux commentaires en ligne qui détaillent les fonctions, la documentation système offre une vue à vol d'oiseau, révélant l'ensemble du paysage d'une application. Cette perspective est cruciale pour repérer les problèmes inter-composants ou les vulnérabilités dans les flux utilisateurs qui sont souvent invisibles au niveau du code.
Imaginez une revue de sécurité comme une partie de Command & Conquer. Vous commencez avec une carte en grande partie obscurcie. Au fur et à mesure que vous explorez, les documents système agissent comme des unités de reconnaissance, dévoilant l'architecture complète — permissions, interactions Snap-dApp, interactions utilisateurs. Cette vue d'ensemble progressive permet aux réviseurs de retracer les parcours utilisateurs, comme suivre les mouvements des unités de jeu, pour repérer des chemins qui pourraient contourner la sécurité.
De plus, une documentation système complète devrait contenir des remarques pertinentes en matière de sécurité et, idéalement, les résultats d'un exercice de modélisation des menaces. Elle doit fournir une vue d'ensemble claire des principaux composants, interactions, risques, acteurs et flux utilisateurs typiques. Cela aide les réviseurs à se concentrer sur les zones prioritaires et à repérer les écarts par rapport aux spécifications.
Pour les développeurs, une bonne documentation système n'est pas qu'une formalité administrative ; c'est une carte partagée qui guide les stratégies offensives et défensives, transformant les revues de sécurité de simples sondages à l'aveugle en opérations stratégiques.
Cette couche comprend une grande variété de matériaux, tels que des articles, des pages d'accueil, des billets de blog, des vidéos de démonstration, et bien plus encore.
Ces informations concernent principalement les aspects commerciaux, mais elles répondent largement à la question « Quoi ? » tandis que toutes les couches précédentes répondaient à la question « Comment ? » avec différents niveaux de détail.
Un nouvel arrivant rencontrera très probablement votre projet à travers ce type de matériel, il est donc judicieux de garder cette couche aussi simple et visuelle que possible. De plus, ce type de matériel est généralement le seul qui montre le logiciel en action — comment un utilisateur peut passer de l'état A à l'état B en utilisant votre logiciel. En le voyant en action, les gens se familiarisent avec l'idée principale de votre logiciel, leur permettant de faire des suppositions sur son fonctionnement sous le capot.
Par exemple, l'écran principal de la page d'accueil de MSQ affiche en grandes lettres : « USE THE INTERNET COMPUTER WITH METAMASK ». Après avoir lu cette simple phrase, le lecteur pourrait deviner : « Ah, donc c'est un Snap de portefeuille qui peut stocker des tokens de la blockchain Internet Computer. Il fonctionne probablement de la même façon que les autres Snaps pour d'autres blockchains, en utilisant simplement les technologies de l'écosystème de développement d'IC » — ce qui est une supposition 100 % correcte.
Commentaire Diligence Notre expérience avec MSQ et de nombreux autres projets blockchain a constamment montré qu'une documentation claire et de haut niveau n'est pas seulement bénéfique — elle est essentielle tant pour l'adoption par les utilisateurs que pour la sécurité. Lors de notre revue du Snap de MSQ, nous avons été agréablement surpris par leur approche de documentation multi-couches. Une vidéo de présentation de leur développeur nous a rapidement mis à niveau. Nous pouvions comprendre les fonctionnalités du Snap avant même d'examiner le code. Cette vue d'ensemble de haut niveau présentait l'interface utilisateur, avec des commentaires sur les comportements attendus et les flux utilisateurs typiques. De tels supports visuels sont inestimables, permettant aux experts en sécurité de saisir beaucoup plus rapidement les « chemins heureux » encodés dans l'application et de rechercher des vulnérabilités souvent cachées en dehors de ces chemins. Cela, combiné à une présentation en direct du snap et du code, constitue généralement le début idéal d'une revue de sécurité.
Cette partie est probablement la plus importante pour la sécurité de votre projet. Votre code peut être 100 % exempt de bugs, et votre infrastructure peut être protégée par des mesures valant des millions de dollars. Mais tous ces efforts ne signifieraient rien si votre conception contient une faille fondamentale pouvant être exploitée par des acteurs malveillants.
Bien que les exemples spécifiques varient selon les cas d'utilisation, nous proposons plusieurs conseils universels.
Au début de MSQ, nous avons établi des principes de sécurité fondamentaux qui s'alignent sur notre vision :
L'équipe MSQ ne sait rien : Nous ne collectons aucune information sensible sur les utilisateurs, y compris les matériaux de clés, les données de session d'autorisation ou les détails de compte.
Le matériel cryptographique ne quitte jamais le Snap : L'entropie MetaMask protégée de l'utilisateur est traitée exclusivement dans le Snap, générée à la demande et immédiatement supprimée après utilisation.
MSQ est déterministe : Les utilisateurs peuvent récupérer tous leurs fonds, identités et paires de clés de manière déterministe en utilisant leur phrase de récupération racine sans avoir besoin de connaissances supplémentaires.
MSQ est axé sur la confidentialité : Nos efforts accordent la priorité absolue à la vie privée des utilisateurs.
Ces principes sont adaptés aux besoins spécifiques de MSQ. Cependant, l'équipe MetaMask fournit également un ensemble de directives de sécurité pour les développeurs de Snap, auxquelles MSQ adhère, disponibles ici.
Par exemple, il existe un principe de permissions minimales, qui signifie essentiellement que moins votre Snap demande de permissions à un utilisateur, meilleure est sa sécurité. MSQ ne demande que 4 permissions :
endowment:rpc
snap_dialog
snap_manageState
snap_getEntropy
Nous n'avons pas besoin de endowment: network access car MSQ est uniquement responsable de la signature des transactions, pas de leur livraison à l'IC — la dapp intégrante est responsable de cette dernière.
Vous devriez faire de même dans votre Snap — prenez la directive par défaut de MetaMask, étendez-la avec vos règles spécifiques et suivez-les.
Commentaire Diligence Nous disons à nos clients : « La sécurité n'est pas une fonctionnalité que l'on ajoute ; c'est un principe autour duquel on conçoit. » L'établissement par MSQ de principes de sécurité fondamentaux dès le début du projet est exactement ce que nous recherchons. Trop souvent, les projets traitent la sécurité comme une réflexion après coup, ajoutant des mesures une fois l'architecture principale définie. Cette approche de rattrapage laisse inévitablement des failles fondamentales que les correctifs au niveau du code ne peuvent pas vraiment résoudre.
Chez Consensys Diligence, nous fournissons des services d'experts en sécurité, des outils, et nous défendons les droits des utilisateurs finaux. Cela inclut s'assurer que le matériel de clés des utilisateurs reste sécurisé dans les limites de confiance du portefeuille, sans jamais être exposé involontairement en dehors de cette zone. Nous nous concentrons également sur la préservation de la vie privée des utilisateurs, en empêchant idéalement même les fuites de métadonnées ou d'informations de canal latéral vers des tiers. De plus, nous encourageons les snaps à ne demander que les permissions minimales nécessaires au fonctionnement — le principe du moindre privilège.
La posture proactive de MSQ s'aligne sur ces principes. En accordant la priorité à la sécurité dès le départ, ils construisent une base plus solide — intrinsèquement plus résistante aux vulnérabilités.
Il s'agit davantage d'une méta-directive — c'est un principe qui devrait être mis en œuvre dans tout logiciel : des jeux en ligne aux systèmes bancaires.
L'exemple le plus notable de cela dans MSQ est notre approche de la gestion des identités. Comme vous le savez peut-être, la majorité des portefeuilles fournissent à l'utilisateur un ensemble d'identités (adresses, comptes, etc.). Cet ensemble peut être accessible par n'importe quelle dapp, avec le consentement de l'utilisateur. Par exemple, pour signer des transactions.
Cela est très utile pour les intégrations entre dapps, car n'importe quelle dapp peut invoquer des méthodes de smart-contract d'autres dapps au nom de l'utilisateur et étendre ainsi mutuellement leurs capacités. Par exemple, une plateforme de paiement crypto peut appeler les smart-contracts d'Uniswap pour échanger automatiquement les tokens de l'acheteur afin qu'ils correspondent à ce que le vendeur s'attend à recevoir comme paiement pour un bien ou service particulier.
Mais cela est préjudiciable à la sécurité, car des sites frauduleux peuvent inciter les gens à signer des transactions malveillantes et vider leurs portefeuilles.
En contraste, MSQ adopte la technique de délimitation d'identité — chaque dapp (chaque origine d'URL distincte) dispose de son propre ensemble séparé d'identités utilisateur avec lesquelles elle peut interagir, sans possibilité d'interagir avec les identités de l'utilisateur provenant d'autres dapps. Cela résout non seulement le problème des sites frauduleux, mais contribue également grandement à la confidentialité, car les dapps ne peuvent plus suivre l'utilisateur et voir avec quels smart-contracts (appelés canisters dans l'IC) il interagit. Cette méthode, inspirée de Internet Identity et de la spécification WebAuthn, atténue considérablement les risques de sécurité.
Par exemple, si une dapp bien connue est compromise, les portefeuilles traditionnels seraient vulnérables sur toutes les dapps. En revanche, la délimitation d'identité de MSQ confine la menace à la dapp compromise, empêchant des dommages plus étendus.
Cependant, cette méthode limite l'intégration directe entre les dapps, car les utilisateurs ont des identités distinctes sur chacune. MSQ propose des solutions pour des scénarios spécifiques, comme permettre le partage d'identité entre dapps avec double consentement, utile pour des situations comme les changements de nom de domaine.
De plus, MSQ garantit que les données auxquelles une dapp peut accéder sont strictement liées à l'identité concernée, sécurisant davantage les informations des utilisateurs et maintenant la confidentialité entre différentes applications.
Commentaire Diligence Le compromis d'une intégration directe limitée entre dApps est une réflexion approfondie. Dans nos évaluations des risques, nous discutons souvent du « budget de sécurité » — en reconnaissant qu'une sécurité parfaite peut entraver la fonctionnalité. MSQ a dépensé ce budget judicieusement. En limitant les interactions inter-dApps, ils ont considérablement réduit l'un des risques les plus graves (l'abus généralisé d'identité) tout en préservant les fonctions essentielles du portefeuille.
Nous avons déjà parlé du code brièvement lorsque nous avons abordé la documentation. Ici, nous souhaitons mettre l'accent sur quelques autres aspects du code, qui sont davantage liés à la technique qu'à la lisibilité.
« Solide » signifie ici que le code se comporte de manière prévisible, couvrant toutes les entrées attendues et inattendues. Par exemple, comment votre Snap devrait-il réagir si on lui donne une chaîne base64 alors qu'il attend du hex ? Ou si des méthodes sont appelées dans une séquence non prévue, ou si une méthode RPC non définie est invoquée ?
Pour répondre à ces incertitudes, il faut :
Une gestion claire des erreurs : Assurez-vous que chaque branche et cas dans votre code est vérifié et traité de manière appropriée. Dans le Snap de MSQ, nous utilisons les vérifications exhaustives de TypeScript dans les instructions switch-case pour détecter tout appel de méthode inattendu, comme illustré ci-dessous :
Cette configuration capture les cas où un identifiant de méthode RPC inconnu est utilisé.
Assainissement des entrées : La validation des données d'entrée par rapport aux types et formats attendus peut être complexe, mais elle est essentielle pour la sécurité. Nous utilisons la bibliothèque zod en TypeScript à cette fin, étendant le système de types de TypeScript aux vérifications à l'exécution. Zod permet des définitions de schémas détaillées, garantissant que seules les données valides sont traitées.
Par exemple, notre méthode SNAP_METHODS.protected.identity.login utilise un schéma zod pour valider rigoureusement les entrées :
Ici, ZOrigin et ZIdentityId ne sont pas de simples chaînes ou nombres, mais des sous-types spécifiquement validés, garantissant que les entrées sont non seulement correctes en termes de type, mais aussi contextuellement appropriées.
En définissant les schémas zod aussi précisément que possible, vous pouvez résoudre préventivement de nombreux problèmes potentiels. Les auditeurs ont recommandé d'appliquer une validation stricte dans MSQ, ce qui, une fois mis en œuvre, a identifié et rectifié plusieurs risques de sécurité.
Commentaire Diligence Ce n'est pas la première fois que nos clients nous disent que la mise en œuvre d'une validation plus stricte basée sur nos recommandations pour un scénario d'attaque particulier a révélé plusieurs autres risques de sécurité. Cela correspond précisément à notre expérience et c'est pourquoi nous préconisons toujours une validation stricte des entrées pour réduire la surface d'attaque. Dans de nombreuses revues de sécurité, nous commençons par examiner attentivement la validation des entrées. Son renforcement expose souvent des problèmes latents — un effet domino où la correction d'une vulnérabilité en révèle une autre. C'est un signal clair que le projet prend nos retours au sérieux, renforçant itérativement leur système. Avec une surface d'attaque réduite, il devient progressivement plus difficile pour les attaquants d'exploiter avec succès les faiblesses.
Chez MSQ, nous considérons qu'il est de notre devoir de fournir aux développeurs de dapps une bibliothèque intuitive, facilitant une interaction correcte et efficace avec notre Snap. Cela permet non seulement à MSQ, mais aussi aux développeurs tiers, de maintenir des bases de code propres et solides.
Une telle bibliothèque est bénéfique pour plusieurs raisons :
Simplifie la complexité de l'API : Nous abstraisons les complexités du Snap dans une API conviviale. Par exemple, la bibliothèque client de MSQ utilise CBOR pour l'encodage des données, contournant les contraintes de JSON-RPC et épargnant aux développeurs la complexité de l'encodage et du décodage manuel des données.
Garantit des interactions sécurisées et directes : Certaines fonctionnalités du Snap sont exclusives à notre dapp compagnon. Pour faciliter cela, nous gérons les processus de redirection et de transfert de données, assurant un flux transparent via postMessage. Cette gestion interne garantit que les développeurs tiers interagissent avec notre Snap via une API claire et directe.
Améliore la clarté sémantique : Une API propre est plus qu'un simple outil ; c'est un medium de communication, rendant le code plus lisible et compréhensible, exempt de l'encombrement des processus complexes d'encodage/décodage et des couches opérationnelles supplémentaires.
En accordant la priorité à ces aspects, MSQ vise à créer un écosystème où notre Snap et les dapps intégrantes peuvent fonctionner efficacement et en toute sécurité.
Commentaire Diligence L'approche de MSQ concernant l'intégration de code tiers via leur bibliothèque démontre un engagement à simplifier le développement tout en maintenant la sécurité. Bien qu'au cœur du système, la sécurité doive être strictement appliquée dans le contexte du Snap, une bibliothèque orientée dapp peut fournir un moyen pratique de communiquer avec le Snap. Cependant, il convient toujours de noter que le développeur de la dapp doit garantir une interaction sécurisée avec le Snap et un encodage sûr des données lorsqu'il est utilisé dans le contexte de la dapp.
La récente backdoor XZ a une fois de plus souligné l'importance de se prémunir contre l'introduction de code malveillant dans certaines de vos dépendances. Chez MSQ, nous utilisons pnpm pour gérer les dépendances, mais il n'y a en réalité aucune différence dans le gestionnaire de paquets que vous préférez. Voici deux choses que nous faisons chez MSQ pour nous protéger contre de tels vecteurs d'attaque :
L'utilisation de pnpm install --save <package-name> installe généralement la dernière version d'un paquet, conformément à la spécification semver, qui permet les mises à jour automatiques vers des versions plus récentes non cassantes. Cela est indiqué par le symbole caret (^) dans package.json, signifiant une plage de versions acceptables :
"zod": "^3.22.4" // Installs version 3.22.4 or newer up to 4.0.0Cependant, pour prévenir les risques liés aux mises à jour malveillantes, il est plus sûr de verrouiller les dépendances à des versions spécifiques :
Éliminez le caret (^) de votre package.json pour fixer chaque version de dépendance. Supprimez les fichiers de verrouillage existants et node_modules, puis exécutez pnpm install pour vous aligner strictement sur les versions définies.
Utilisez le flag --save-exact pour les futures installations (pnpm install --save-exact <package-name>) pour éviter les mises à jour automatiques.
La confiance est un facteur dans cette décision. Par exemple, chez MSQ, nous considérons les espaces de noms de dépendances @metamask et @dfinity comme sûrs et autorisons les mises à jour dans leur plage semver. Cependant, ce faisant, soyez prudent face aux vulnérabilités potentielles provenant des dépendances transitives.
Commentaire Diligence La migration de projets vers des versions de dépendances exactes a permis d'éviter d'innombrables problèmes :
Cela a empêché les mises à jour silencieuses de réintroduire des vulnérabilités corrigées.
Cela a évité le « décalage de version » où différents modules voient des comportements de bibliothèque différents.
Cela a été crucial dans les investigations post-incident, nous permettant de reproduire l'environnement exact. Chaque prochaine mise à jour peut être malveillante, dans n'importe quel espace de noms, n'importe quel paquet. En examinant les paquets utilisés et en se liant uniquement à des versions connues comme sûres, on empêche les mises à jour accidentelles et on réduit davantage la surface d'attaque pour les attaques sur la chaîne d'approvisionnement. Faire confiance à certains fournisseurs est acceptable, tant que les nouvelles versions sont vérifiées manuellement pour s'assurer qu'elles ne contiennent pas de code malveillant avant utilisation. Notez que les paquets particulièrement bien connus utilisés par de nombreux projets sont des cibles de choix pour les acteurs malveillants et, comme le passé l'a montré, toute bibliothèque centrale de ce type peut succomber à des attaques sophistiquées sur la chaîne d'approvisionnement (voir l'attaque backdoor XZ)
Pour garantir la cohérence au sein de votre équipe et maintenir des builds reproductibles, commitez vos fichiers de verrouillage dans le système de contrôle de version. Chez MSQ, nous utilisons pnpm workspaces et turborepo, nécessitant un seul fichier de verrouillage racine, pnpm-lock.yaml. Cependant, votre configuration pourrait nécessiter la maintenance de plusieurs fichiers de verrouillage ; tous devraient être versionnés pour garantir la cohérence de l'environnement.
Commentaire Diligence
Cette pratique, parfois négligée comme une simple commodité de développement, est en fait un composant critique du maintien d'une base de code sécurisée et stable. Nos années d'audit de smart contracts, de composants blockchain et maintenant de MetaMask Snaps ont montré à maintes reprises que les builds reproductibles ne sont pas seulement un avantage, mais une exigence fondamentale de sécurité. Commiter les fichiers de verrouillage est une pièce du puzzle pour réduire la surface d'attaque des attaques sur la chaîne d'approvisionnement. Quand npm install n'est plus une loterie, les versions concrètes et les checksums laissent une piste d'audit dans le dépôt, les builds sont plus déterministes, et les discussions « Ça marche sur ma machine » appartiennent au passé.
Bien que cela ne concerne pas directement notre Snap, comprendre comment traiter efficacement les résultats d'audit est essentiel.
Dès que l'équipe d'auditeurs signale une découverte, vous devriez commencer à travailler sur un correctif. La taille et la complexité du correctif dépendent clairement de la découverte, mais voici un conseil pour le rendre plus petit et plus propre — corrigez la cause, pas le symptôme, dans la mesure du possible.
Par exemple, chez MSQ, les auditeurs ont découvert qu'il était possible d'injecter des caractères de contrôle Markdown dans nos messages de consentement MetaMask. Au lieu de corriger chaque message de consentement séparément, en apportant de multiples modifications dans différentes parties du code, nous avons simplement redéfini les éléments text() et heading() (de @metamask/snaps-sdk), afin qu'ils fassent d'abord passer leur contenu par la fonction escapeMarkdown() avant de le rendre. Cela nous a permis de simplement remplacer les expressions import dans tous les fichiers contenant des messages de consentement par nos éléments personnalisés, au lieu de corriger chaque invocation de text() et heading() séparément, ce qui constituait un correctif bien plus propre.
Une résolution efficace améliore non seulement le problème spécifique, mais sécurise également préventivement contre des vulnérabilités non détectées.
Commentaire Diligence Trop souvent, nous voyons des projets adopter une approche de « jeu du taupe » en matière de sécurité, corrigeant chaque problème individuel au fur et à mesure qu'il apparaît sans considérer la classe de vulnérabilité sous-jacente. En s'attaquant à la cause profonde des problèmes et en n'hésitant pas à éliminer globalement des classes de vulnérabilités, MSQ démontre qu'il comprend la sécurité non pas comme une série de correctifs, mais comme une discipline holistique. En tant qu'experts en sécurité, nous ne pouvons que recommander à nos clients de ne pas se précipiter dans les corrections et de prendre suffisamment de temps pour transformer une découverte de sécurité en un événement ayant un effet positif sur la sécurité du projet.
Voilà qui conclut nos réflexions sur la façon de naviguer avec succès dans un audit de sécurité MetaMask Snaps. Le respect de ces directives a aidé l'équipe MSQ à recevoir un rapport positif de l'équipe Diligence. Nous espérons que le partage de l'expérience MSQ vous aidera dans vos préparatifs d'audit de sécurité, garantissant un processus approfondi et efficace.
Consensys Diligence a aidé un large éventail de projets dans l'écosystème blockchain à s'assurer que leurs protocoles sont prêts pour le lancement et conçus pour protéger les utilisateurs. Nous serons ravis de vérifier votre Snap pour ces vulnérabilités et bien d'autres dans le cadre d'un audit personnalisé. Contactez-nous et obtenez un devis !
Traduit par IA. Peut contenir des erreurs. Veuillez toujours vérifier les informations.