Escaping is the process of converting special characters into a representation that ensures they are interpreted as data, not executable code.

Example:

<  →  <
>  →  >
"  →  "
'  →  &#x27;

However, escaping is not universal. Each browser parser (HTML, JavaScript, CSS, URL, JSON) has different rules, meaning escaping must always be context‑specific.

2. Why Escaping Fails in Real Applications

A common but dangerous assumption is:

escape(userInput)

Used everywhere.

This approach fails because:

  • HTML escaping does not protect JavaScript
  • JavaScript escaping does not protect URLs
  • JSON escaping does not protect script execution

The browser does not see "escaped input", it sees syntax inside a specific parser.

3. HTML Body Context

Context

<div>USER_INPUT</div>

Parser

HTML parser

Characters That Must Be Escaped

< > & " '

Secure Rendering

<script>alert(1)</script>

Common Vulnerability

element.innerHTML = userInput

This causes the browser to re‑parse input as HTML, making escaping ineffective if done incorrectly.

4. HTML Attribute Context

Context

<input value="USER_INPUT">

Parser

HTML attribute parser

Required Escaping

" ' < > &

Why This Context Is Dangerous

Attributes can introduce new attributes or event handlers:

" autofocus onfocus=alert(1) x="

If quotes are not properly escaped, the browser treats the input as HTML structure, not data.

5. JavaScript String Context

Single‑Quoted Strings

var data = 'USER_INPUT';

Required Escaping

' \ newline

Example

\' \\ \n

Double‑Quoted Strings

var data = "USER_INPUT";

Required Escaping

" \ newline

Key Point

Escaping must happen before JavaScript execution, not after rendering.

6. JavaScript Template Literals

Context

var data = `USER_INPUT`;

Required Escaping

` \ $

Additional Risk

Template literals allow expression evaluation:

${expression}

This makes them extremely dangerous if user input reaches them unescaped.

7. JavaScript Execution Context (Critical)

Dangerous Sinks

eval()
new Function()
setTimeout(string)
setInterval(string)

Example

eval('searchResults(' + responseText + ')');

Why Escaping Does Not Work Here

JavaScript execution contexts cannot be safely escaped.

Correct rule:

NEVER eval user input

8. JSON Context

Context

{"searchTerm":"USER_INPUT"}

Required Escaping

" \ control characters

Proper JSON Encoding

\" \\ \n \t

Common Anti‑Pattern

eval('callback(' + jsonResponse + ')')

This converts JSON into JavaScript code, completely bypassing JSON safety guarantees.

9. URL Context

Context

<a href="USER_INPUT">

Required Encoding

Percent‑encoding

Example

%3A %2F %26 %3F

Critical Mistake

HTML‑escaping URLs instead of URL‑encoding them.

10. JavaScript URL Assignment

Context

location.href = USER_INPUT

Why Escaping Is Not Enough

Certain schemes are executable:

javascript:
data:

Correct defense:

Allow‑list http and https only

11. CSS Context

Context

style="background: USER_INPUT;"

Risks

CSS supports functions:

url()

Legacy browsers support:

expression()

CSS escaping is fragile and should be avoided for untrusted input.

12. DOM Insertion APIs

Dangerous APIs

innerHTML
outerHTML
document.write
insertAdjacentHTML

Safe Alternatives

textContent
innerText
setAttribute (with validation)

13. Framework Escaping Pitfalls

React

JSX auto‑escapes by default

Danger:

dangerouslySetInnerHTML

Angular

{{ value }}

Danger when sanitization is bypassed.

Vue

v-html

Directly disables escaping.

14. A Generic Exploitation Thought Process (High‑Level)

1. Identify the rendering context
2. Identify escaping behavior
3. Determine the active parser
4. Understand how the browser interprets the data
5. Locate dangerous sinks

This is a mental model, not an exploit recipe.

15. Defensive Best Practices

ESCAPE BY CONTEXT
NEVER REUSE ESCAPERS
1. Identify the rendering context
2. Use the correct encoder
3. Avoid dangerous sinks
4. Validate before escaping
5. Prefer safe APIs

16. Conclusion

Escaping is not a function.