Use when the value lands inside an HTML attribute:
<span title="HERE">,<a href="HERE">,<input value=HERE>.
escHtmlAttr is strict: anything outside [A-Za-z0-9,.\-_] is
rewritten as an HTML entity. That whitelist is small enough to be safe
in quoted, single-quoted and unquoted attribute values.
- A handful of code points use named entities (
",&,<,>) when they have one. - Everything else uses numeric character references (
&#xHH;or&#xHHHH;). U+0000–U+001F(except tab, LF, CR) andU+007F–U+009Fare replaced withU+FFFDbecause they cannot appear inside an HTML document.
use InitPHP\Escaper\Esc;
$untrusted = 'faketitle onmouseover=alert(1);';
echo '<span title=' . Esc::esc($untrusted, 'attr') . '>hello</span>';
// <span title=faketitle onmouseover=alert(1);>hello</span>The space, =, parentheses and semicolon all become entity references,
so the browser sees one attribute value rather than the attacker's
extra onmouseover handler.
echo Esc::esc('ş', 'attr');
// ş
echo Esc::esc('🚀', 'attr');
// 🚀- URL attributes (
href,src,action) —escHtmlAttronly protects the attribute delimiters. Run the URL throughescUrlfirst. - Event handlers (
onclick,onfocus, …) — those are JavaScript contexts, not HTML attribute contexts. ApplyescJsto the JS code, thenescHtmlAttrthe result if it sits inside anon*=…attribute. styleattribute — that is a CSS context. UseescCssinsidestyle="...".
The escaper short-circuits when the input is empty or contains nothing but ASCII digits — those values are already attribute-safe:
Esc::esc('', 'attr'); // ''
Esc::esc('12345', 'attr'); // '12345'