Reflected XSS template literal unicode escaped
| Field | Value |
|---|---|
| Platform | PortSwigger Web Security Academy |
| Difficulty | Practitioner |
| Vulnerability | Reflected XSS — Template Literal Injection via ${} |
| Injection Point | JavaScript template literal inside <script> block |
| Goal | Execute alert(0) via template literal expression interpolation |
Lab — Reflected XSS: Template Literal Injection via ${}¶
Solution Walkthrough¶
Searching for teto reveals the injection point is inside a JavaScript template literal:
var message = `0 search results for 'teto'`;
document.getElementById('searchMessage').innerText = message;
All standard escape characters are blocked: <>, ', ", \, and backticks are encoded or escaped. There is no way to break out of the template literal using those characters.
Step 1 — Understand template literal expression interpolation
Template literals (backtick strings) support ${} expression interpolation — JavaScript evaluates whatever is inside the ${} and inserts the result into the string:
var teto = "test";
// Regular string — ${ } is treated as literal characters
console.log("Teto is equals to ${teto}");
// → Teto is equals to ${teto}
// Template literal — ${ } is evaluated as JavaScript
console.log(`Teto is equals to ${teto}`);
// → Teto is equals to test
The ${} syntax only works inside backtick strings — not inside ' or " strings. Since our injection point is already inside a template literal, we can use ${} directly without needing to break out.
Step 2 — Inject an expression
${alert(0)}
Resulting JavaScript:
var message = `0 search results for '${alert(0)}'`;
document.getElementById('searchMessage').innerText = message;
When the template literal is evaluated, JavaScript calls alert(0) to compute the expression inside ${}. Alert fires and the lab is solved :P
Why This is a Unique Context¶
This lab represents a fourth JavaScript injection context — distinct from all previous ones:
| Context | Escape character | Technique |
|---|---|---|
Single-quoted string '...' |
' |
Close string, inject statement |
Double-quoted string "..." |
" |
Close string, inject statement |
| Script block (no string) | </script> |
Close script tag, inject new one |
Template literal `...` |
${} |
No escape needed — interpolate directly |
Template literal injection is arguably simpler than the others — there is no need to break out of the string at all. The ${} syntax is designed to evaluate JavaScript expressions, and since it already exists inside the template literal context, injecting ${alert(0)} is valid syntax that the JavaScript engine happily executes.