Table of Contents
3. Escaping and Output Encoding — Keeping Untrusted Data in Its Place
Once untrusted data enters the system, it must be handled with care.
Validation shapes the data
— but escaping determines where that data is allowed to go.
Security is not just about rejecting bad input.
It’s about ensuring that even valid input cannot break out of its intended context.
This page introduces the mental model of contextual output encoding
— the quiet discipline that keeps untrusted data in its place.
1. Escaping Is About Context, Not Characters
Escaping is not a universal transformation.
It is a context‑specific contract.
The same string must be escaped differently
depending on where it is placed:
- HTML text
- HTML attributes
- JavaScript
- CSS
- URLs
- SQL queries
- shell commands
- file paths
There is no “one escape to rule them all.”
Security comes from choosing the right encoding for the right context.
2. HTML Escaping — The Default for Web Output
When outputting untrusted data into HTML,
the safe default is to
escape:
< > & " '
This prevents:
- HTML injection
- broken markup
- accidental tag creation
- XSS payloads
Most template engines do this automatically.
Security comes from not disabling it.
3. Attribute Escaping — A Different Boundary
HTML attributes are a different context
with different risks.
Example:
<input value="<?= $escaped ?>">
Here, escaping must prevent:
- breaking out of the attribute
- injecting new attributes
- injecting event handlers
- closing the tag early
Attribute escaping is stricter than HTML escaping.
Treat it as a separate boundary.
4. JavaScript Escaping — The Most Dangerous Context
Never place untrusted data directly into JavaScript.
If you must, use:
- JSON encoding,
- strict escaping,
- safe wrappers
Example:
<script>
const data = <?= json_encode($safeData, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) ?>;
</script>
This prevents:
- string termination
- code injection
- XSS payloads
- unexpected execution
JavaScript is the most fragile boundary.
Treat it with respect.
5. URL Encoding — Preventing Injection Through Navigation
URLs are another context entirely.
Example:
<a href="/search?q=<?= urlencode($query) ?>">
URL encoding prevents:
- breaking query strings
- injecting new parameters
- altering navigation
- redirect manipulation
Never concatenate untrusted data into URLs without encoding.
6. SQL Parameterization — Escaping Is Not Enough
SQL is not escaped — it is parameterized.
Example: code php> $stmt = $pdo→prepare('SELECT * FROM users WHERE email = ?'); $stmt→execute([$email]); </code> Parameterization prevents:
- SQL injection
- broken queries
- type confusion
- malicious operators
Escaping SQL manually is fragile and error‑prone.
Use parameters. Always.
7. Shell Escaping — Avoid It Entirely When Possible
Shell commands are extremely dangerous.
If you must use them:
- escape arguments
- avoid concatenation
- use safe wrappers (escapeshellarg, escapeshellcmd)
- prefer built‑in PHP functions instead
The safest shell command is the one you never run.
8. Template Engines — Trust the Defaults, Not the Exceptions
Most modern template engines:
- escape HTML by default
- escape attributes when needed
- provide safe helpers
- prevent accidental raw output
- Security collapses when developers:
- disable escaping
- use “raw” output
- bypass the template engine
- mix PHP and HTML manually
Trust the defaults.
Avoid the escape hatches.
9. Escaping Complements Validation — It Does Not Replace It
Validation shapes the data.
Escaping keeps it in its lane.
You need both:
- validation ensures the data is what you expect
- escaping ensures the data stays where it belongs
Security is layered, not singular.
Summary
Escaping and output encoding are about context, not characters.
A secure system:
- escapes based on where the data goes
- treats HTML, attributes, JS, URLs, SQL, and shell as separate boundaries
- uses parameterization for SQL
- avoids raw JavaScript injection
- trusts template engine defaults
- never disables escaping without a clear reason
Security is not about distrusting the data
—it’s about respecting the boundaries.
This page describes secure defaults and common practices in modern PHP. It is not a complete security guide, and it does not replace formal audits or framework‑specific documentation. These principles are consistent enough to be useful, but security always requires context, judgment, and ongoing review.
