How does output encoding stop XSS, and why do templating frameworks encode by default?
By converting dangerous characters into harmless display equivalents (< → <) at render time, so attacker input shows as text instead of executing as markup. Good frameworks do this by default, and you must not turn it off for untrusted data.
The key insight: input validation alone can't catch everything, so the last line of defense is encoding data as it leaves the app into a specific output context. HTML encoding turns <script> into the literal text <script>, which the browser renders as visible characters rather than running it.
Most templating engines escape automatically, and each provides an explicit "raw / don't escape" switch — the classic XSS hole is flipping that switch on user data:
| Framework | Safe (escapes) | Unsafe (raw — only for trusted HTML) |
|---|---|---|
| JSF (Java) | <h:outputText value="#{bean.x}" /> |
escape="false" |
| Blade (Laravel) | {{ $x }} |
{!! $x !!} |
| Thymeleaf | th:text |
th:utext |
| React | {x} |
dangerouslySetInnerHTML |
Rule: Keep the default encoding on for anything that could contain user input; only ever use the raw variant for HTML you fully control.
But encoding must match the context — HTML-entity encoding is correct inside an HTML body, but wrong inside a <script> block, an attribute, a URL, or CSS. See the contextual-encoding card next.