FILTER_UNSAFE_RAW est le filtre PHP identifié par la constante 516 — la même valeur que FILTER_DEFAULT, puisque les deux désignent en réalité le même filtre. Sans drapeau, il ne fait rigoureusement rien : il retourne la chaîne telle qu'elle a été reçue, sans supprimer ni encoder quoi que ce soit. Ce sont les drapeaux qu'on lui associe qui déterminent son comportement réel.
Ce que ce filtre ne fait jamais, avec ou sans drapeau : retirer des balises HTML. C'est un point que beaucoup de débutants supposent à tort, et l'étape 6 le démontre concrètement.
Pour la liste complète des drapeaux PHP, notre référence complète des drapeaux des filtres détaille chacun d'eux.
Étape 1 — Observer le comportement par défaut : que fait FILTER_UNSAFE_RAW sans drapeau ?
En résumé : sans drapeau, FILTER_UNSAFE_RAW renvoie une copie strictement identique à l'entrée. Aucun caractère n'est touché, pas même les caractères de contrôle invisibles ou les balises HTML.
<?php
$input = "Bonjour <b>tout le monde</b>\x07";
// \x07 est un caractère de contrôle invisible (BEL, ASCII 7)
$result = filter_var($input, FILTER_UNSAFE_RAW);
var_dump($input === $result);
echo "Longueur avant : " . strlen($input) . "\n";
echo "Longueur après : " . strlen($result) . "\n";
?>
Résultat attendu :
bool(true) Longueur avant : 29 Longueur après : 29
La chaîne d'entrée et la chaîne de sortie sont strictement identiques, balise HTML comprise. C'est cette absence totale de traitement qui explique le nom du filtre : unsafe raw, autrement dit "brut, non sécurisé".
Étape 2 — Supprimer les caractères indésirables : quelle différence entre STRIP_LOW et STRIP_HIGH ?
STRIP_LOW retire les caractères dont la valeur ASCII est inférieure à 32 — les caractères de contrôle comme le saut de ligne ou la tabulation. STRIP_HIGH retire ceux dont la valeur est supérieure à 127 — utile en théorie pour les caractères non-ASCII, mais avec un piège que l'exemple suivant révèle.
<?php
$a = "Ligne1\nLigne2";
$resultatLow = filter_var($a, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW);
echo "STRIP_LOW : " . $resultatLow . "\n";
$b = "café";
// "café" fait 5 octets en UTF-8 : c-a-f + 2 octets pour "é"
$resultatHigh = filter_var($b, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_HIGH);
echo "STRIP_HIGH : " . $resultatHigh . "\n";
echo "Longueur avant : " . strlen($b) . " / après : " . strlen($resultatHigh);
?>
Résultat attendu :
STRIP_LOW : Ligne1Ligne2 STRIP_HIGH : caf Longueur avant : 5 / après : 3
⚠ Si vos textes en français perdent leurs accents après un STRIP_HIGH, ce n'est pas un bug : le "é" occupe deux octets au-dessus de 127 en UTF-8, et les deux disparaissent entièrement. STRIP_HIGH est donc à éviter sur du texte accentué — il détruit l'information au lieu de la nettoyer.
Étape 3 — Encoder au lieu de supprimer : à quoi servent ENCODE_LOW et ENCODE_HIGH ?
Contrairement à STRIP, qui détruit les caractères visés, ENCODE les convertit en entité HTML numérique — la donnée reste présente, juste sous une autre forme. C'est le choix à privilégier quand on veut garder une trace de ce qui a été filtré.
<?php $c = "Ligne1\nLigne2"; $resultatLow = filter_var($c, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_LOW); echo "ENCODE_LOW : " . $resultatLow . "\n"; $d = "café"; $resultatHigh = filter_var($d, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_HIGH); echo "ENCODE_HIGH : " . $resultatHigh; ?>
Résultat attendu :
ENCODE_LOW : Ligne1 Ligne2 ENCODE_HIGH : café
Le "é" n'a pas disparu : il a été remplacé par les deux entités à et ©, une par octet UTF-8. La donnée d'origine reste reconstituable, contrairement à STRIP_HIGH.
Étape 4 — Protéger le caractère & : pourquoi utiliser ENCODE_AMP ?
Le caractère & a un rôle spécial : il sépare les paramètres dans une URL et introduit les entités HTML. Laissé tel quel dans une valeur destinée à une URL ou un attribut HTML, il peut casser la structure de la page ou du lien. ENCODE_AMP le neutralise sans y toucher au reste de la chaîne.
<?php $e = "Tom & Jerry"; $resultat = filter_var($e, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP); echo $resultat; ?>
Résultat attendu :
Tom & Jerry
Étape 5 — Cumuler plusieurs drapeaux : comment les combiner avec l'opérateur | ?
Les drapeaux ne s'excluent pas entre eux. L'opérateur bit à bit | permet d'en appliquer plusieurs en un seul appel — utile quand une même chaîne contient à la fois des caractères accentués, des sauts de ligne et des esperluettes.
<?php
$f = "Café & Cie\n";
$resultat = filter_var(
$f,
FILTER_UNSAFE_RAW,
// on cumule les trois drapeaux avec l'opérateur |
FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_AMP | FILTER_FLAG_ENCODE_LOW
);
echo $resultat;
?>
Résultat attendu :
Café & Cie
Étape 6 — Éviter le piège de sécurité : pourquoi FILTER_UNSAFE_RAW ne protège pas contre le XSS ?
Aucun des drapeaux vus jusqu'ici ne touche aux chevrons < et > d'une balise HTML. FILTER_UNSAFE_RAW n'est donc jamais suffisant, à lui seul, pour afficher en sécurité une donnée saisie par un utilisateur dans une page HTML.
<?php
$g = "<script>alert('x')</script>";
$resultat = filter_var($g, FILTER_UNSAFE_RAW);
var_dump($g === $resultat);
echo $resultat;
?>
Résultat attendu :
bool(true)
<script>alert('x')</script>
⚠ La balise <script> ressort intacte, quel que soit le drapeau utilisé. Pour afficher sans risque une donnée utilisateur dans du HTML, il faut la passer par htmlspecialchars() — FILTER_UNSAFE_RAW sert à nettoyer des caractères ponctuels, pas à sécuriser un affichage HTML.
Récapitulatif : le cycle complet en un seul script
<?php // 1. Aucun drapeau : rien ne change $brut = filter_var("Bonjour <b>monde</b>\x07", FILTER_UNSAFE_RAW); // 2. STRIP : supprime (et peut détruire des accents) $sansControle = filter_var("Ligne1\nLigne2", FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW); // 3. ENCODE : préserve la donnée sous forme d'entité $encode = filter_var("café", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_HIGH); // 4. ENCODE_AMP : protège le caractère & pour les URLs $amp = filter_var("Tom & Jerry", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP); // 5. Cumul de drapeaux avec l'opérateur | $cumul = filter_var( "Café & Cie\n", FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_HIGH | FILTER_FLAG_ENCODE_AMP | FILTER_FLAG_ENCODE_LOW ); // 6. Pour un affichage HTML sécurisé, toujours ajouter htmlspecialchars() $secure = htmlspecialchars($brut, ENT_QUOTES, 'UTF-8'); echo $brut . "\n" . $sansControle . "\n" . $encode . "\n" . $amp . "\n" . $cumul . "\n" . $secure; ?>
Retourner à la liste des filtres
Par carabde : 20 août 2014 | Mis à jour le 14 juillet 2026