logo oujood
🔍

Filtre PHP FILTER_UNSAFE_RAW

Chaque drapeau testé et vérifié en ligne de commande, avec la sortie exacte que vous obtiendrez sur votre machine.
PHP cours tutoriel

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.

  📋 Copier le code

<?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.

  📋 Copier le code

<?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é.

  📋 Copier le code

<?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&#10;Ligne2
ENCODE_HIGH : caf&#195;&#169;

Le "é" n'a pas disparu : il a été remplacé par les deux entités &#195; et &#169;, 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.

  📋 Copier le code

<?php
$e = "Tom & Jerry";
$resultat = filter_var($e, FILTER_UNSAFE_RAW, FILTER_FLAG_ENCODE_AMP);
echo $resultat;
?>

Résultat attendu :

Tom &#38; 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.

  📋 Copier le code

<?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&#195;&#169; &#38; Cie&#10;

É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.

  📋 Copier le code

<?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

  📋 Copier le code

<?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