security
Output Escaping
Output escaping converts data into a safe representation for the place it is inserted. HTML text, HTML attributes, JavaScript, URLs, CSS, SQL, and shell commands are different contexts with different rules.
What Matters
- Escape as late as possible, at the output boundary.
- Use
htmlspecialchars()with quotes and UTF-8 for ordinary HTML text and attributes. - Do not reuse HTML escaping for JavaScript, URLs, SQL, or shell commands.
- Prefer template engines with automatic HTML escaping.
- Keep trusted markup separate from plain user-controlled text.
Practical Example
<?php
declare(strict_types=1);
function escapeHtml(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
echo '<p>' . escapeHtml('<script>alert("x")</script>') . '</p>' . PHP_EOL;
// Prints:
// <p>&lt;script&gt;alert(&quot;x&quot;)&lt;/script&gt;</p>
In Application Work
The most common job-facing case is rendering names, comments, search terms, and validation messages in templates. Review the exact output context rather than asking whether input was already sanitised.
HTML Text And Attributes
htmlspecialchars() is suitable for ordinary HTML text and quoted attribute values:
<?php
declare(strict_types=1);
function html(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
$title = '" onclick="alert(1)';
echo '<input value="' . html($title) . '">' . PHP_EOL;
// Prints:
// <input value="&quot; onclick=&quot;alert(1)">
Keep attributes quoted. Avoid constructing raw markup from fragments of user input.
Other Contexts Need Other Tools
For JavaScript data, encode a value as JSON rather than inserting a hand-escaped string. For URL query values, use http_build_query() or rawurlencode(). For SQL values, bind prepared-statement parameters. For shell arguments, avoid shell execution when possible and use purpose-built APIs.
One escaping helper cannot safely cover every output target.
Store Data, Not Escaped Display Text
Store the original validated text and escape when rendering. Pre-escaping before storage leads to double escaping, mixes presentation with data, and fails when the same value later appears in JSON, email, or a CLI report.
What To Check
Before moving on, make sure you can:
- escape output for its specific context;
- use safe HTML escaping for text and quoted attributes;
- explain why validation is not output escaping;
- avoid mixing trusted HTML with plain user text;
- choose a context-specific encoding tool instead of one universal escape function.
Practice
Practice: Escape A Profile Card
Render a profile name and biography as HTML text.
Requirements
- Escape the name and biography at the HTML boundary.
- Use UTF-8 and escape quotes.
- Show that markup supplied as data is displayed as text.
Show solution
Both values are plain text, so HTML text escaping is the correct boundary control.
<?php
declare(strict_types=1);
function escapeHtml(string $value): string
{
return htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
function profileCard(string $name, string $bio): string
{
return '<h2>' . escapeHtml($name) . '</h2><p>' . escapeHtml($bio) . '</p>';
}
echo profileCard('Amo <Admin>', '<strong>Hello</strong>') . PHP_EOL;
// Prints:
// <h2>Amo &lt;Admin&gt;</h2><p>&lt;strong&gt;Hello&lt;/strong&gt;</p>
The code escapes when rendering, which keeps stored data independent from one output format.