Pas malveillant. Juste négligent — ce qu'un module PrestaShop laisse derrière lui

Un module PrestaShop payant que nous avons découvert sur la boutique d'un client chargeait une police décorative depuis un CDN tiers sur chacune de ses pages — la page d'accueil, chaque catégorie, chaque produit, le panier, le checkout. Cette police servait à un seul endroit : l'écran de configuration du module lui-même, tout au fond du back-office, que voyait à peu près une seule personne dans l'entreprise.
Voici ce que cette négligence a réellement coûté, mesuré sur la page d'accueil en production. Le module ajoutait un nouveau domaine tiers, trois requêtes supplémentaires par page (une feuille de style et deux fichiers de police) et environ 159 Ko de poids dont aucun navigateur de visiteur n'avait besoin. Comme la feuille de style se trouvait dans le <head> de la page, elle bloquait le rendu : chaque visiteur découvrant le site attendait une résolution DNS et une négociation TLS vers un serveur dont le commerçant n'avait jamais entendu parler, avant que la page puisse finir de s'afficher. Sur une connexion mobile bridée, le Largest Contentful Paint est passé de 2,4 à 2,9 secondes et le score de performance Lighthouse est tombé du début des 90 au milieu des 80. Rien de catastrophique. Juste un impôt, prélevé discrètement à chaque chargement de page, pour toujours, au profit d'une police que personne, hors de l'administration, n'a jamais vue.
Le rayon d'impact, c'était toute la boutique ; la fonctionnalité, c'était un seul écran. Cet écart — entre ce qu'un module touche et ce à quoi il sert réellement — est le sujet entier de cet article. Nous avons cadré la ressource pour que la police ne se charge que sur la page qui l'utilise, et les chiffres sont revenus à leur niveau de départ. Le correctif a pris un après-midi. Découvrir le problème a demandé un navigateur et une habitude.

Ce module n'était pas un malware. C'est justement là tout le propos. Personne ne cherchait à nuire à qui que ce soit. Un développeur voulait que sa page de configuration soit soignée, il a choisi une police et collé l'extrait de code CDN fourni par le site de la police — puis, par la même habitude du copier-coller, il a aussi enregistré cette même feuille de style sur le hook global de l'en-tête du front-office, alors que seule la page de configuration s'en servait. Chaque décision, prise isolément, était minime et raisonnable. La somme fut une régression de performance à l'échelle de toute la boutique, qu'aucun « mais c'est un petit module » n'aurait su prédire. La négligence a suffi. C'est généralement le cas.
Si vous voulez voir le peu qu'il faut, voici la forme de l'erreur — reconstituée, ce n'est pas le code du fournisseur d'origine. L'écran de configuration lui-même charge parfaitement cette police dans le back-office ; le dommage vient d'une seconde ligne, superflue, qui enregistrait en plus la même feuille de style sur le hook de l'en-tête du front-office — celui qui se déclenche sur chaque page de la boutique, là où rien ne l'utilise :
// Runs on EVERY page of the storefront — home, category, product, checkout
public function hookDisplayHeader($params)
{
// …yet nothing on the storefront uses this font — the settings screen loads it itself.
$this->context->controller->addCSS(
'https://3p-cdn.net/fancy-display/style.css' // third-party, render-blocking
);
}
Rien ici n'est malveillant ; ce sont quelques lignes qui font exactement ce qu'elles disent. L'ennui, c'est que ce hook n'a rien à voir avec l'écran de configuration auquel la police est destinée. displayHeader s'exécute sur la boutique, si bien qu'une police prévue pour une seule page d'administration est téléchargée par chaque client — pour rien. Le correctif consiste à supprimer entièrement l'enregistrement côté boutique et à laisser le back-office continuer de charger la police là où elle sert réellement :
// The storefront never shows this font, so the front-office hook loads nothing.
public function hookDisplayHeader($params)
{
return;
}
// It loads only on this module's own settings screen in the back office —
// self-hosted, so no third-party domain and no extra DNS + TLS round-trip.
public function hookDisplayBackOfficeHeader($params)
{
if (Tools::getValue('configure') !== $this->name) {
return; // every other admin page pays nothing either
}
$this->context->controller->addCSS($this->_path.'views/css/fancy-display.css');
}
Même fonctionnalité, même police — la boutique ne charge désormais plus rien qu'elle n'utilise, et l'impôt à l'échelle du site disparaît en même temps que le domaine tiers. Cet écart entre les deux versions, c'est toute la différence entre un module qui reste dans son couloir et un module qui fait discrètement payer chaque page pour une fonctionnalité que presque personne ne voit. Personne n'a eu besoin d'être négligent volontairement.
Le problème, c'est que les modules se font passer pour des applications
La plupart des commerçants raisonnent au sujet des modules comme ils raisonnent au sujet des applications de leur téléphone. Une application est cloisonnée : elle s'exécute dans son propre jardin clos, elle ne peut pas aller fouiller dans les autres applications, et si elle vous déplaît, vous la supprimez et votre téléphone se retrouve exactement dans l'état où il était. Ce modèle mental est confortable, et pour PrestaShop il est totalement faux.
Un module PrestaShop n'est pas une application cloisonnée. C'est du code PHP non cloisonné qui s'exécute avec l'ensemble des privilèges de votre boutique. Une fois installé et activé, il peut s'accrocher à chaque page qui s'affiche, lire et écrire dans n'importe quelle table de votre base de données — commandes, clients, prix, configuration —, enregistrer des overrides qui remplacent discrètement le comportement du cœur, déposer des fichiers dans votre thème, ajouter des colonnes et des tables, planifier des tâches en arrière-plan et appeler des services externes en votre nom. Ce n'est pas un invité dans un jardin clos. C'est un membre du personnel qui détient les clés de tout le bâtiment, et vous l'avez embauché en cliquant sur « installer ».
Un module n'est pas une fonctionnalité que l'on active. C'est du code à qui vous confiez les clés de votre boutique. La question n'est jamais « cette fonctionnalité est-elle sympa » — c'est « est-ce que je fais confiance à ce code pour tout ce que ma boutique est capable de faire ».
Rien de tout cela n'est un défaut de PrestaShop. C'est précisément cette puissance qui rend la plateforme assez extensible pour faire tourner une véritable entreprise. Mais cela signifie que le modèle de sécurité que vous portez en tête — le modèle de l'application — ne vous protège de rien.
Rendons cela concret : un seul module activé peut atteindre tout ce qui suit à la fois — il s'accroche à chaque page qui s'affiche, ajoute et modifie des tables en base de données, dépose des fichiers d'override par-dessus les classes du cœur, édite votre thème, charge des ressources sur tout le site, planifie des tâches en arrière-plan, lit et écrit vos commandes et vos fiches clients, et appelle des services externes. Une application sur votre téléphone ne peut rien faire de tel au téléphone. Un module PrestaShop peut faire tout cela à votre boutique — ce qui explique pourquoi « il n'y a qu'à l'installer pour voir » est une décision bien plus lourde qu'il n'y paraît.

« Ça marchait dans ma boutique de test », c'est là que les ennuis commencent
Les quatre mots les plus coûteux du développement de modules sont « ça marchait chez moi ». Un développeur construit un module, l'installe sur une boutique de test vierge, clique partout, constate que ça fonctionne, et publie. L'ennui, c'est qu'une boutique de test vierge n'a rien à voir avec une vraie boutique.
Votre vraie boutique possède un thème personnalisé qui redéfinit des templates que le module tenait pour acquis. Elle tourne peut-être en multiboutique, où un module testé uniquement sur la boutique 1 se comporte mal, en silence, sur la boutique 2. Elle utilise une version de PHP précise, peut-être plus ancienne, ou plus récente, que celle dont disposait le développeur. Elle a des dizaines d'autres modules déjà accrochés aux mêmes pages, qui se disputent la même sortie. Elle a du trafic réel, une couche de cache, un checkout en production qui encaisse de vrai argent, et — le plus important — elle sera mise à jour un jour, vers une nouvelle version de PrestaShop avec laquelle le module n'a jamais été testé. « Ça a marché une fois, sur une boutique, sur une version » n'est la garantie de rien du tout. Un module doit continuer de fonctionner à travers tout cela, pendant des années. C'est une promesse fondamentalement plus difficile que « ça marche », et l'essentiel du risque se loge dans la différence. C'est aussi pourquoi la qualité des modules compte plus que leur quantité, et c'est la moitié cachée de ce qui rend réellement PrestaShop lent.
Ce qui subsiste quand vous désactivez ou désinstallez
Voici la croyance qui fait le plus de dégâts : « si ça pose problème, je n'aurai qu'à le désinstaller et tout reviendra à la normale ». Parfois c'est vrai. Souvent ça ne l'est pas, et la distinction mérite d'être comprise avec précision — parce que c'est la version confiante de cette affirmation qui laisse les boutiques discrètement cassées.
Désactiver un module empêche ses hooks de s'exécuter à l'exécution. Cela aide vraiment : le module cesse d'injecter ses ressources et d'exécuter son code sur chaque page, si bien qu'un problème de performance ou d'affichage en production se dissipe généralement aussitôt. La désactivation est le bon premier réflexe en cas d'urgence. Mais désactiver ne revient pas sur ce que le module a déjà fait, et n'y touche pas.
Désinstaller va plus loin et exécute la propre routine de nettoyage du module — et cette routine ne supprime que ce que son auteur a pris la peine d'écrire pour le supprimer. Ce qui ne revient pas de manière fiable de lui-même :
- Modifications de la base de données et de la configuration. De nouvelles tables, de nouvelles colonnes et des lignes de configuration peuvent rester en place. Certains modules conservent délibérément vos données à la désinstallation pour que vous ne perdiez pas vos réglages lors d'une réinstallation — un choix raisonnable, mais seulement s'ils vous le disent.
- Données de commandes et de clients. Tout ce qui a été écrit dans vos commandes, vos factures ou vos fiches clients pendant le fonctionnement normal, ce sont vos données commerciales réelles. Désinstaller le module ne les supprime pas, et ne devrait pas les supprimer — mais il peut les laisser dans un format que seul ce module comprenait.
- Overrides et modifications du thème. Des fichiers déposés dans
/overrideou dans votre thème peuvent survivre au module. Un override obsolète laissé en place après la désinstallation est une cause classique de « ma boutique est cassée et rien de ce que j'ai désactivé ne l'a réparée ». - Intégrations externes. Les données que le module a envoyées à un service tiers — un flux, un CRM, une plateforme d'analyse ou de marketing — échappent déjà au contrôle de votre boutique. Désinstaller ne change rien à l'autre bout de la chaîne.
La phrase exacte est donc : la désactivation arrête l'hémorragie, mais la désinstallation ne défait pas les écritures en base de données, les modifications de configuration, les données de commandes et de clients, les overrides, les modifications du thème ni les appels externes qu'un module a déjà effectués. « Je n'aurai qu'à le désinstaller » est un plan pour la fonctionnalité. Ce n'est pas un plan pour l'empreinte.
Il est utile de se représenter les trois états côte à côte. Désactiver arrête l'exécution du module. Désinstaller exécute sa routine de nettoyage. Mais toute une colonne d'éléments — données écrites dans vos commandes et vos clients, configuration, overrides, modifications du thème, et tout ce qui a déjà été envoyé à un service extérieur — survit aux deux, à moins que l'auteur du module n'ait écrit du code pour les défaire et que vous ayez vérifié que c'était bien le cas. C'est cette dernière colonne qui surprend les gens au pire moment possible.

Nous avons publié cette erreur, nous aussi
Il serait malhonnête d'écrire tout cela comme si cela n'arrivait qu'aux autres. Ce n'est pas le cas. Nous concevons et vendons des modules PrestaShop pour gagner notre vie, et nous avons commis la même catégorie d'erreur.
Sur l'un de nos propres modules, un script du front-office dont une seule fonctionnalité avait besoin s'est retrouvé enregistré sur un hook qui se déclenche sur chaque page, plutôt que seulement sur les contrôleurs où la fonctionnalité apparaît réellement. Fonctionnellement, tout marchait, alors c'est passé en revue et ça a été publié. C'est un audit de performance, des mois plus tard — le même genre d'audit que dans cet article — qui a repéré un petit script se chargeant sur tout le site sans raison, sur des pages qui ne l'utilisaient jamais. Le coût n'était pas spectaculaire : quelques kilo-octets et un peu de temps d'analyse sur chaque page, à travers tout le catalogue, jusqu'à ce que nous le corrigions. Mais il était réel, il était le nôtre, et « ça marche » l'avait laissé passer sans broncher.
Ce qui a changé, ce n'est pas un sermon sur la nécessité d'être plus prudent. Nous en avons fait une question à laquelle la revue doit répondre pour chaque ressource et chaque hook : faut-il vraiment que ce soit global, ou est-ce que ça a sa place sur les pages qui l'utilisent ? Une cicatrice devient une règle, et la règle attrape la suivante. Voilà la version honnête de la qualité — non pas « nous ne faisons jamais d'erreurs », mais « nous avons construit ce qui les attrape avant vous ». C'est la même discipline qui permet d'amener une vraie boutique avec plus de 80 modules à un score PageSpeed de 99 : non pas moins de modules, mais des modules qui restent dans leur couloir — ce qui constitue tout le cahier des charges de notre suite Performance Revolution.
Alors, l'IA n'est-elle pas la coupable dans tout ça ?
Vous pourriez vous attendre à ce qu'un éditeur de modules conclue en accusant l'IA — du code bon marché généré par IA qui inonderait le marché de camelote. Nous n'allons pas le faire, car ce serait à la fois injuste et hypocrite. Nous recourons nous-mêmes, largement, à l'ingénierie assistée par IA. C'est précisément pour cela que nous ne jugeons pas un module selon qu'une IA y a touché ou non.
L'IA est un accélérateur. Elle rend la bonne ingénierie plus rapide et elle rend l'ingénierie négligente plus rapide, et elle n'a aucun avis sur celle des deux que vous pratiquez. L'erreur de la police sur chaque page précède la vague actuelle d'IA d'une bonne décennie ; des humains pressés en ont écrit un bon paquet. Ce qui distingue un module auquel vous pouvez faire confiance d'un module auquel vous ne le pouvez pas n'a jamais été l'outillage de l'auteur. C'est la gouvernance : y a-t-il un responsable identifié, le code est-il relu, est-il testé, est-il maintenu compatible à mesure que PrestaShop évolue, ses modifications peuvent-elles être défaites, reste-t-il dans son budget de performance, quelqu'un le maintiendra-t-il l'an prochain. Ces questions sont exactement aussi valables que le code ait été tapé par une personne, généré par un modèle, ou — comme c'est désormais la norme — écrit par une personne et un modèle ensemble. La propriété, la revue et les tests sont le sujet. La paternité est une distraction.
Jugez-nous à la même aune
Nous vendons des modules, nous aussi, il serait donc facile de lire tout ceci comme un « achetez plutôt chez nous ». Ne nous croyez pas sur parole — c'est tout l'esprit de la chose. Le geste équitable consiste à tenir tous les éditeurs, nous compris, au même standard, et la bonne nouvelle, c'est que la plupart des vérifications importantes ne réclament aucune connaissance de PHP. Vous pouvez les mener depuis un navigateur, sur une copie de préproduction de votre boutique : installez le module, ouvrez l'onglet Réseau de votre navigateur sur votre page d'accueil (pas la page du module), et comptez ce qui a changé.
Nous avons rédigé la procédure complète sous forme de référence en langage clair — comment évaluer un module PrestaShop avant de l'installer sur une boutique en production — et nous la voulons comme un outil à retourner contre notre catalogue aussi volontiers que contre celui de n'importe qui. Si vous préférez que quelqu'un s'en charge pour vous, c'est exactement ce que font nos audits de performance et de sécurité, et notre analyse de sécurité gratuite est un point de départ sans frais. Retournez la checklist contre nous. Nous préférerions que vous le fassiez.
Questions fréquentes
Désinstaller un module supprime-t-il tout ce qu'il a créé ?
Non — pas de façon fiable. La désinstallation exécute la propre routine de nettoyage du module, qui ne supprime que ce que son auteur a écrit pour le supprimer. Les tables de la base de données, les lignes de configuration, les fichiers dans /override, les modifications du thème et toute donnée déjà envoyée à un service externe peuvent tous survivre. Elle ne devrait par ailleurs jamais supprimer vos commandes ni vos fiches clients, car ce sont vos données commerciales réelles. Partez du principe que la désinstallation range la fonctionnalité, pas l'empreinte tout entière.
Un seul module peut-il vraiment ralentir toute ma boutique ?
Oui. Quand un module charge des ressources ou exécute du code sur un hook global — un hook qui se déclenche sur chaque page — ce coût est payé par chaque page, y compris votre page d'accueil et votre checkout, même les pages où la fonctionnalité n'apparaît jamais. C'est exactement ainsi qu'une police destinée à un seul écran d'administration a fini par taxer toute une boutique.
Un module est-il dangereux du simple fait qu'une IA a aidé à l'écrire ?
Non. L'IA est un accélérateur, pas un verdict. Ce qui rend un module digne de confiance, c'est la propriété, la revue, les tests, la compatibilité, la réversibilité et la discipline de performance — et cela vaut que le code ait été écrit par une personne, par un modèle, ou par les deux. Jugez la gouvernance, pas la paternité.
Comment vérifier concrètement un module avant de l'installer ?
Sur une copie de préproduction, installez-le et observez ce qui change : nouvelles requêtes tierces dans l'onglet Réseau de votre page d'accueil, nouvelles tables en base de données, checkout qui fonctionne toujours, et désinstallation qui se fait proprement. Nous avons rédigé la démarche complète, pas à pas, dans comment évaluer un module PrestaShop avant de l'installer.
Les meilleurs modules sont ennuyeux
Après toutes ces histoires de guerre, la conclusion est presque décevante, et c'est bien là le propos. Un bon module est ennuyeux. Il fait l'unique chose qu'il a annoncée. Ses ressources ne se chargent que là où elles servent. Il ne touche qu'aux données dont il a besoin, vous dit ce qu'il conserve, et nettoie ce qu'il peut. Il survit à votre prochaine mise à jour de PrestaShop sans drame. Et le signe le plus sûr de sa qualité, c'est que, six mois après l'avoir installé, vous avez complètement oublié qu'il est là.
L'excitation, chez un module, est presque toujours le bruit de quelque chose qui tourne mal sur une page qu'il n'aurait jamais dû toucher. L'ennui est l'objectif. L'ennui, c'est ce à quoi « ça marche tout seul » ressemble vraiment vu de l'intérieur — et cela vaut la peine d'être vérifié, délibérément, avant qu'un inconnu détenant les clés de toute votre boutique ne vienne s'installer.
Commentaires
Aucun commentaire pour le moment. Soyez le premier !
Soyez le premier à poser une question ou à partager un retour utile.
Laisser un commentaire
Partagez une question, un détail de pose ou un retour qui pourrait aider un autre lecteur.