When you need it
Whenever a value someone typed, or a code sample, has to sit inside HTML. Skip the escaping
and <script> runs for real (that is XSS), while <div>
simply vanishes from the page.
Putting code in a blog post is the same problem. < has to become
< before the browser will draw it as a character instead of a tag.
Five characters is the whole job
| Character | Entity | If you leave it |
|---|---|---|
& | & | Joins the text after it and is read as some other entity |
< | < | Read as the start of a tag |
> | > | Read as the end of a tag |
" | " | Ends an attribute value right there |
' | ' | Ends a single-quoted attribute value |
The trap when you write this yourself is that & has to be replaced
first. Do it later and the < you just produced becomes
&lt; — escaped twice.
The quotes option
For text that only ever lands in the body, you can leave quotes alone. But if it goes into an
attribute value — <input value="here"> — turn it on. A single
quote character ends the attribute, and whatever follows can be
onerror=. That is why the default is on.
The numeric reference option
This rewrites accented letters, non-Latin scripts and emoji as é-style
numeric references. If your document has <meta charset="utf-8">, you do not
need it. Turn it on only for an old mail template or a legacy system whose encoding you do not
trust — the output gets much bigger and stops being readable by a human.
Does escaping alone stop XSS?
In a body-text position, mostly yes. But the rules differ inside
href="javascript:…", inside <script>, and inside a
style attribute. Each context needs its own handling, so in a real application
you are safer leaving it to your framework's automatic escaping.