Le WordPress d'aujourd'hui, décodé pour les développeurs

Sécurité

« Warning: preg_match() expects parameter 2 to be string » révèle une entrée non filtrée avant le motif

Ce warning PHP, souvent ignoré en production, signale presque toujours qu'un tableau a été transmis là où une chaîne était attendue, avec un risque de contournement de filtre.

Par WordPress Développement • 29 octobre 2020 • 4 min de lecture • Aucun commentaire
« Warning: preg_match() expects parameter 2 to be string » révèle une entrée non filtrée avant le motif

« Warning: preg_match() expects parameter 2 to be string, array given ». Ce message apparaît dans le journal PHP d’un site qui filtre un paramètre de recherche avec une expression régulière. Beaucoup de développeurs le traitent comme un warning mineur, corrigent l’affichage et passent à autre chose. C’est une erreur d’appréciation.

Symptôme : un warning qui n’empêche pas la page de s’afficher

Le code concerné ressemble typiquement à ceci :

$recherche = $_GET['q'] ?? '';

if (preg_match('/^[a-zA-Z0-9\s]+$/', $recherche)) {
    $resultats = rechercher_produits($recherche);
}

En usage normal, un visiteur saisit du texte dans un champ de recherche et $_GET['q'] contient une chaîne. Le warning apparaît lorsque la requête envoie ?q[]=texte au lieu de ?q=texte. PHP interprète alors la notation avec crochets comme une instruction de construire un tableau, et $_GET['q'] devient ['texte'] plutôt qu’une chaîne.

Diagnostic : pourquoi ce comportement n’est pas anodin

preg_match() émet un warning et retourne false quand son second paramètre n’est pas une chaîne. Le code ci-dessus interprète ce false comme un échec de validation et n’exécute pas la recherche : dans cet exemple précis, la conséquence visible se limite à une page de résultats vide. Mais la même structure, appliquée à une validation censée bloquer une entrée dangereuse avant un traitement plus sensible, produit un résultat bien plus problématique : le test échoue silencieusement, la condition if n’est jamais vraie, et le code de traitement associé n’est jamais atteint, ce qui masque le vrai problème plutôt que de le révéler clairement à l’équipe de développement.

Le risque réel apparaît quand la logique est inversée, par exemple avec une négation : if (!preg_match(...)) { rejeter(); }. Dans ce cas, un warning et un retour false provoquent l’exécution de la branche de rejet, ce qui semble sûr à première vue. Mais si le code suivant traite malgré tout $recherche comme une chaîne plus loin dans le flux, sans revalider son type, un tableau peut se propager dans des fonctions qui ne l’attendent pas, avec des conséquences imprévisibles selon leur implémentation.

L'essentiel à retenir : Le warning signale un type inattendu, pas une simple erreur cosmétique ; Un tableau injecté peut contourner un filtre attendu sur une chaîne ; Valider le type avant le filtrage évite le contournement

Correctif : forcer le type avant toute validation

La correction ne consiste pas à supprimer le warning, mais à garantir que l’entrée est bien une chaîne avant d’atteindre preg_match() :

$recherche_brute = $_GET['q'] ?? '';

if (!is_string($recherche_brute)) {
    wp_die('Parametre de recherche invalide.', '', ['response' => 400]);
}

$recherche = sanitize_text_field($recherche_brute);

if (preg_match('/^[\p{L}\p{N}\s]+$/u', $recherche)) {
    $resultats = rechercher_produits($recherche);
}

La fonction is_string() agit comme une garde explicite. Un tableau reçu à la place d’une chaîne provoque désormais un rejet immédiat et documenté, avec un code de réponse HTTP clair, plutôt qu’un warning silencieux suivi d’un comportement difficile à retracer.

Prévention : traiter les warnings PHP comme des signaux, pas du bruit

  • Configurer un environnement de développement avec error_reporting(E_ALL) et l’affichage des erreurs activé, pour voir ces warnings avant la mise en production.
  • Ajouter une vérification de type sur toute variable issue de $_GET, $_POST ou $_REQUEST avant de la transmettre à une fonction qui attend explicitement une chaîne.
  • Surveiller le journal d’erreurs de production pour ce type de warning précis, car sa fréquence augmente généralement lors d’une tentative de sondage automatisé du site.

Ce même symptôme au-delà de preg_match()

D’autres fonctions natives de PHP réagissent de façon comparable à un type inattendu, notamment str_contains(), strpos() ou trim(), qui attendent également une chaîne en premier argument. Le même schéma de diagnostic s’applique : un warning apparaît dans le journal, la fonction renvoie une valeur qui peut être interprétée à tort comme un résultat valide, et le code continue son exécution sur une base faussée. Repérer ce warning précis dans un journal de production devrait systématiquement déclencher une recherche de l’origine du tableau injecté là où une chaîne était attendue.

En résumé

Un warning PHP sur un type de paramètre inattendu n’est jamais purement cosmétique : il révèle qu’une entrée utilisateur a atteint une fonction sensible sans validation de type préalable. Le corriger en amont, par une vérification explicite avec is_string(), referme une porte que la simple présence d’une expression régulière ne suffisait pas à verrouiller.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi