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 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 example
<?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 example
<?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.