Security Tip: Is `strip_tags()` Secure?

[Tip#63] PHP includes a some really handy security-focused functions, but you need to know how to use them correctly, or you risk leaving a significant vulnerability waiting to be exploited! 😱

Security Tip: Is `strip_tags()` Secure?

⚠️ Want me to hack into your app and tell you how I did it, so you can fix it before someone else finds it? Book in a Laravel Security Audit and Penetration Test! 🕵️


It’s common to find older PHP apps use some of the built-in security functions, such as `strip_tags()`1, `htmlspecialchars()`2, and `htmlentities()`3. They each work in different ways and but are they actually secure enough to use? And when should you use each of them?

Let’s take a look at `strip_tags()` and hopefully answer those question4!

According to the PHP docs:

This function tries to return a string with all NULL bytes, HTML and PHP tags stripped from a given string. It uses the same tag stripping state machine as the fgetss() function.

The function itself has two parameters, the first is required and is the string value being stripped, and the second is an optional list of allowed HTML tags.

strip_tags(string $string, array|string|null $allowed_tags = null): string

But is it secure?

Let’s answer that question through a couple of examples…

return strip_tags("Hello <b>World</b>!")

// Hello World!

✅ So far so good, it does what it says it does - strip HTML tags out of strings!

return strip_tags("Hello <img src=x onerror=\"alert('Boom!')\"> World!");

// Hello  World!

✅ As we’d expect, it strips out complex tags too.

$string = "Hello <img src=x onerror=\"alert('Boom!')\"> World!";

return strip_tags($string, "<img>"); 

// Hello <img src=x onerror="alert('Boom!')"> World!

❌ Unfortunately, it blindly allows the entire tag, which includes any XSS payloads. You cannot use `strip_tags()` with user input when you want to allow some tags. Instead, what you need is a fully featured HTML Purifier.

$value = strip_tags("' onload=\"alert('Boom!')\" '"); 

return "<input type='text' name='comments' value='{$value}'>";

// <input type='text' name='comments' value='' onload="alert('Boom!')" ''>

❌ As we should expect, it’s not context aware so although it will remove tags, it won’t escape anything else. This means you cannot use it inside tag attributes safely.

Summary

`strip_tags()` is safe to use when you’re removing entirely HTML tags from content going straight on the page outside any attributes or complex HTML strictures.

Don’t use it if you need to allow specific tags (use a Purifier instead), and don’t use it inside attributes or complex structures.


Looking to learn more?
Security Tip #44: Avoiding XSS with HtmlString
▶️ In Depth #15: Mass-Assignment Vulnerabilities