CWE-476 : déréférencement de pointeur nul, la panne du cas non prévu
- Accueil
- Référentiels & catalogues
- Cwe
- CWE-476 : déréférencement de pointeur nul, la panne du cas non prévu
CWE-476 : déréférencement de pointeur nul, la panne du cas non prévu
Section intitulée « CWE-476 : déréférencement de pointeur nul, la panne du cas non prévu »Treizième du CWE Top 25 2025. Le libellé officiel, NULL Pointer Dereference, se traduit par « déréférencement de pointeur nul » ; le catalogue accepte quatre abréviations selon les langages : NPD, null deref, NPE pour l’exception Java, nil pointer dereference pour Go. Quatre noms pour un même oubli : ne pas avoir prévu qu’il n’y aurait rien.
Un standardiste reçoit l’instruction de transférer l’appel au bureau indiqué sur la fiche. Quand la fiche est vide, il n’a aucune consigne : il ne demande pas, il ne raccroche pas, il s’effondre. Le standard est alors muet pour tout le monde. CWE-476 décrit ce standard.
→ Lire l’explication complète de la marmotte
Ce que la classe recouvre exactement
Section intitulée « Ce que la classe recouvre exactement »Le produit déréférence un pointeur qu’il suppose valide et qui vaut nul. Déréférencer, c’est aller voir ce qui se trouve à l’adresse indiquée ; l’adresse nulle est celle qui, par convention, ne désigne rien. Le système refuse l’accès, et le processus s’arrête.
La faiblesse n’est donc pas « un pointeur vaut nul » : c’est une situation normale, qui signifie « absence de valeur ». Elle est dans l’écart entre une supposition et la réalité : le code a été écrit comme si l’allocation réussissait toujours, comme si la recherche trouvait toujours, comme si le champ facultatif était toujours rempli.
Les sources habituelles sont au nombre de trois, et toutes les trois sont des valeurs de retour qu’on n’a pas lues :
- une allocation mémoire qui échoue, cas rare mais pas inexistant, notamment sur les systèmes contraints ;
- une recherche qui ne trouve pas : élément absent d’une table, clé manquante dans une configuration, enregistrement supprimé entre deux requêtes ;
- une analyse de données qui renvoie l’absence : champ optionnel non fourni, structure tronquée, message mal formé. C’est la source dominante, parce que les données viennent de l’extérieur et que l’extérieur est créatif.
La conséquence habituelle est l’arrêt du processus, soit un déni de service. Dans certains contextes anciens, et presque exclusivement dans le noyau, un déréférencement de pointeur nul a pu conduire à davantage ; sur les systèmes actuels, où la page zéro n’est pas projetable, cette perspective a largement disparu. C’est une faiblesse de disponibilité, et elle doit être traitée comme telle.
Sa place dans l’arbre
Section intitulée « Sa place dans l’arbre »Détail révélateur : CWE-476 est une base à deux parents, et aucun des deux n’appartient à la famille mémoire.
Le premier est CWE-754, « vérification incorrecte des conditions inhabituelles ou exceptionnelles » : le défaut est rangé parmi les erreurs de gestion de cas particuliers, aux côtés des valeurs de retour ignorées et des exceptions non traitées. Le second est CWE-710, « respect incorrect des standards de codage » : la faiblesse est aussi une affaire de discipline collective.
Cette double parenté a une conséquence directe sur la manière de corriger. On ne traite pas cette classe avec les outils de la famille mémoire : il n’y a ni borne à vérifier, ni durée de vie à suivre. On la traite en rendant obligatoire la vérification des valeurs de retour, ce qui est un problème de convention et d’outillage, non d’architecture.
Elle est, à ce titre, la seule entrée de la famille mémoire apparente du Top 25 qui n’a rien à voir avec les débordements : l’écriture hors limites et la lecture hors limites se trompent sur une taille, celle-ci se trompe sur une existence.
Pourquoi elle est si haut
Section intitulée « Pourquoi elle est si haut »Parce qu’elle est la récolte favorite du test automatisé. Une campagne de génération d’entrées aléatoires contre un analyseur de format produit des plantages par dizaines, et la majorité sont des déréférencements de pointeur nul sur un champ absent ou une structure tronquée. Chaque plantage reproductible devient un signalement, chaque signalement un identifiant.
Parce que les logiciels d’infrastructure plantent cher. Un serveur de noms, un relais de messagerie, un pare-feu, un hyperviseur : dans ces produits, l’arrêt du processus est un incident d’exploitation majeur, et un paquet mal formé envoyé par n’importe qui suffit à le déclencher à volonté. La gravité attribuée reste modérée dans l’échelle commune, mais la fréquence est telle qu’elle suffit à placer la classe au treizième rang.
Parce que les langages modernes ne l’ont pas tous supprimée. Les langages qui distinguent par le type « valeur présente » et « valeur absente » rendent l’oubli impossible à compiler ; ceux qui laissent un null habiter tous les types le gardent en pleine forme, avec un meilleur message d’erreur pour seule différence.
Le mécanisme, et où le site le traite
Section intitulée « Le mécanisme, et où le site le traite »Le site n’a pas de page consacrée à cette classe, dont le mécanisme tient dans un paragraphe : le programme obtient une adresse qui ne désigne rien, va la consulter, et le système interrompt le processus pour accès mémoire invalide. Il n’y a pas de subtilité d’exploitation, et c’est précisément ce qui en fait une faiblesse de disponibilité.
Pour l’effet côté exploitation, défendre un DDoS volumétrique et applicatif décrit ce qu’implique un service qu’on peut arrêter à la demande, avec cette nuance utile : ici, nul besoin de volume, un seul message bien formé suffit, ce qui échappe à toute défense fondée sur le débit.
Côté prévention, revoir le code de sécurité au-delà du linter nomme l’habitude à prendre : lire les valeurs de retour, y compris celles qu’on croit toujours bonnes. Et Rust et la sécurité mémoire par construction décrit le choix de conception qui supprime la classe : un type qui représente explicitement l’absence, et un compilateur qui refuse de l’ignorer.
Ce qu’une équipe en fait
Section intitulée « Ce qu’une équipe en fait »Rendre l’absence explicite dans les types. Quand le langage le permet, c’est la seule correction définitive : l’absence de valeur devient un cas que le compilateur force à traiter. Dans les langages qui ne le permettent pas, les annotations de nullité et les analyseurs qui les vérifient en approchent.
Ne jamais ignorer une valeur de retour, et faire respecter la règle par la chaîne de compilation plutôt que par la relecture. La plupart de ces défauts viennent d’un appel dont personne n’a lu le résultat.
Tester les entrées tronquées et incomplètes. Les jeux de tests contiennent presque toujours des messages valides et des messages invalides, rarement des messages incomplets : champ absent, structure coupée au milieu, liste vide là où l’on attendait un élément. C’est exactement ce que trouvent les campagnes de test automatisé, et c’est bien moins coûteux de le trouver soi-même.
- CWE-476: NULL Pointer Dereference, MITRE, liste 4.20 : définition, parents CWE-754 et CWE-710.
- 2025 CWE Top 25, MITRE : rang 13.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Une équipe qui range cette classe parmi les bogues de confort la traite après les autres, parce qu’elle « ne fait que planter ». Le calcul est juste pour une application de bureau et faux pour un service : un processus qu’un message mal formé arrête à volonté est un service dont la disponibilité appartient à n’importe qui. Les protections habituelles n’y font rien, puisqu’il n’y a ni volume ni répétition à détecter : une requête, un arrêt. Et comme le redémarrage automatique masque le symptôme, le défaut survit longtemps sous la forme d’une instabilité attribuée à la charge, jusqu’à ce que quelqu’un comprenne qu’il suffit de l’envoyer en boucle. Le coût final est celui d’une panne choisie par l’attaquant au moment où elle gêne le plus, sans qu’aucun accès ni aucun privilège n’ait été nécessaire.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Un programme désigne les informations qu’il manipule par leur adresse en mémoire, un peu comme on désigne une maison par son adresse postale. Il existe une adresse conventionnelle qui signifie « rien » : elle sert à dire qu’une information est absente (le client n’a pas de second prénom, la recherche n’a rien trouvé, le fichier n’a pas pu être ouvert).
Le défaut consiste à aller consulter cette adresse comme si elle désignait quelque chose. Le système d’exploitation refuse, et le programme s’arrête immédiatement. Ce n’est pas un vol d’information : c’est une panne.
C’est le défaut que le catalogue CWE appelle CWE-476. Il vient presque toujours de la même cause : le programme a été écrit en supposant que tout se passerait bien, que le champ serait rempli, que la recherche aboutirait, que le message serait complet. Le jour où une donnée arrive incomplète, souvent envoyée depuis l’extérieur, la supposition tombe et le programme avec elle.
Pour une application installée sur un ordinateur personnel, c’est un désagrément. Pour un service partagé (un serveur de courrier, un pare-feu, un service de noms) c’est une panne générale, que n’importe qui peut déclencher en envoyant un message volontairement tronqué, autant de fois qu’il le souhaite. Les défenses habituelles contre les attaques en saturation sont ici inutiles, puisqu’il n’y a pas de saturation : un seul message bien choisi suffit.
La parade est connue et ingrate : vérifier systématiquement que ce qu’on a reçu existe avant de s’en servir. Les langages de programmation récents aident en obligeant le programmeur à traiter le cas de l’absence, faute de quoi le programme ne compile pas : ce qui est plus fiable que la bonne volonté d’une relecture.
À lire aussi
- CWE-416 : usage après libération, le pointeur qui survit à sa mémoireCWE-416, use after free : ce que la variante recouvre, sa place sous CWE-825 et CWE-672, pourquoi elle prospère dans le code concurrent, et son rang 7 au Top 25 2025.
- CWE-122 : débordement de tampon dans le tasCWE-122, heap-based buffer overflow : ce que la variante recouvre, pourquoi le tas se prête mieux à l'exploitation que la pile, son lien avec CWE-416, et son rang 16 au Top 25 2025.
- CWE-121 : débordement de tampon dans la pileCWE-121, stack-based buffer overflow : ce que la variante recouvre, ce que la pile contient d'intéressant pour un attaquant, la confusion avec l'épuisement de pile CWE-674, et son rang 14 au Top 25 2025.
- CWE-120 : débordement de tampon classique, la copie sans mesureCWE-120, copie de tampon sans vérification de la taille de l'entrée : la cause plutôt que le geste, sa place entre CWE-787 et CWE-20, l'héritage des fonctions non bornées, et son rang 11 au Top 25 2025.
Pages voisines
La citent
- CWE-416 : usage après libération, le pointeur qui survit à sa mémoire
- OWASP Top 10 web 2025 : les dix catégories et ce qui a changé
CWE-476 : déréférencement de pointeur nul, la panne du cas non prévu
Elle cite
- Lien dans les deux sens :CWE Top 25 2025 : les vingt-cinq faiblesses logicielles les plus dangereuses
- CWE-125 : lecture hors limites, la fuite qui ne casse rien
- CWE-787 : écriture hors limites, la tête de la famille mémoire
- Comment revoir le code de sécurité au-delà du linter
- Défendre un DDoS volumétrique et applicatif
- Rust et la sécurité mémoire par construction, garanties et limites
: les deux pages se citent l’une l’autre.
