PHP 8: Modern PHP Development · Security for PHP Applications
XSS and Output Escaping
Escape output by context and use templates that auto-escape.
Cross-site scripting happens when untrusted data is rendered as HTML/JS. Escape output at render time, for the right context: htmlspecialchars($v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') for HTML text and attributes, json_encode() with JSON_HEX_TAG flags when embedding in scripts, and URL encoding for URLs. Template engines like Twig and Blade auto-escape by default. Sanitize rich HTML with an allow-list library (HTML Purifier, Symfony HtmlSanitizer) and add a Content Security Policy as defense in depth.
<?php
function e(?string $value): string
{
return htmlspecialchars($value ?? '', ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
?>
<p>Hello, <?= e($user->name) ?></p>
<a href="/search?q=<?= e(urlencode($query)) ?>">Search again</a>
<script>
const config = <?= json_encode($config, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR) ?>;
</script>
Common pitfalls
- Escaping on input and storing escaped data (double-escaping, wrong context later).
- Using Blade's
{!! !!}or Twig's|rawwith user content. - Allowing
javascript:URLs in user-supplied links.
Key points
- Escape on output, per context
- Templates auto-escape — don't bypass them
- Sanitize rich HTML with an allow-list; add CSP
Further reading: OWASP XSS Prevention Cheat Sheet
Practice questions
Why escape on output rather than on input?
Answer
The correct escaping depends on where data is used (HTML, attribute, JS, URL, SQL). Escaping at render time for the specific context is correct; input-time escaping corrupts data and still misses contexts.
When is {!! $html !!} in Blade acceptable?
Answer
Only for trusted HTML or HTML sanitized with an allow-list sanitizer. Never for raw user input.
Open in the app to mark lessons complete, take notes and track your progress.