XSS Prevention in PHP
In this lesson: Stop XSS attacks in PHP — escape output with htmlspecialchars, validate input and set CSP — examples of safe vs unsafe code.
What is XSS
XSS (Cross-Site Scripting) is a common attack where a bad user puts HTML or JavaScript into your page through an input — like a comment or a name field. If you print that input without cleaning it, the script runs in other visitors' browsers, which can steal cookies or hijack accounts.
How an attack happens
Imagine a comment box. A normal user writes "Nice post". An attacker writes:
<script>alert('hacked')</script>
If your page prints this comment directly, the browser runs the script for everyone who views the page. That is XSS. The danger is not in storing the text — it is in printing it without escaping.
The fix: escape output
htmlspecialchars() turns dangerous characters into safe text so the browser shows them instead of running them.
<?php
$comment = "<script>alert('x')</script>";
echo htmlspecialchars($comment);
?>
The <script> now appears as harmless text on the page — it does not run. This one function is your main defence against XSS.
Handling input safely
Store the original value; escape only when you display it.
<?php
$name = $_POST["name"] ?? ""; // store as-is
// ... save to database ...
// when showing on a page:
echo "Hello, " . htmlspecialchars($name);
?>
This way the real value stays intact in your database, and it is made safe only at the moment it appears on screen — the right place to escape.
Safe output rules
- Escape every user-controlled value with
htmlspecialchars()when printing it. - Escape values from URLs too:
$_GETvalues are user input. - Use
ENT_QUOTESto also escape quotes:htmlspecialchars($x, ENT_QUOTES). - Never build HTML by pasting raw input into it.
Common mistakes
- Printing input directly.
echo $_POST["name"]without escaping is the classic XSS hole. - Escaping only some fields. One un-escaped output is enough to be attacked.
- Thinking validation alone stops XSS. Validation is separate; escaping output is the defence.
- Ignoring URL parameters.
$_GETvalues shown on the page must be escaped too.
Summary
- XSS runs an attacker's script in visitors' browsers via unescaped input.
- The fix is to escape output with
htmlspecialchars(). - Store the original value; escape only when displaying it.
- Escape every user-controlled value, including
$_GETfrom URLs. - Validation and escaping are both needed — they do different jobs.
Next, clean incoming data with form validation, or protect the database with prepared statements.
Frequently Asked Questions
What is XSS in simple words?
How does htmlspecialchars stop XSS?
htmlspecialchars() converts special characters like < and > into harmless text codes. So an injected <script> is shown as plain text instead of running. Always use it when printing user input.Where exactly should I escape — input or output?
htmlspecialchars(). Store the original value; escape only when showing it. This keeps the data intact and safe on screen.Is validation enough to stop XSS?
htmlspecialchars() when displayed.