-
Notifications
You must be signed in to change notification settings - Fork 1
Context JavaScript
Use when the value lands inside a JavaScript string literal:
<script>var x = "HERE";</script>,<button onclick="alert('HERE')">.
escJs() whitelists [A-Za-z0-9,._]. Every other character is rewritten as a JavaScript escape sequence:
| Input form | Output form |
|---|---|
Single-byte character (U+0000–U+007F) |
\xNN (upper-case hex) |
BMP multibyte character (U+0080–U+FFFF) |
\uNNNN (upper-case hex) |
Above the BMP (U+10000–U+10FFFF, e.g. emoji) |
UTF-16 surrogate pair: \uHHHH\uHHHH
|
The whitelist explicitly includes ,, ., _ because those are safe in JS string contents and would otherwise generate noisy escape sequences.
escJs() produces a fragment that is safe inside a string literal. It does not add the surrounding quotes — you do. The standard usage is:
<script>
var greeting = "<?= Esc::esc($value, 'js') ?>";
</script>Forgetting the quotes produces invalid JavaScript (not a security issue, but a silent breakage). The dedicated wiki page on this gotcha lives at FAQ → Why is my JavaScript invalid after escaping?.
public function escJs(string $str): string;Or via the facade:
Esc::esc(string $str, 'js', ?string $encoding = null): string;| Throws | When |
|---|---|
InvalidUtf8Exception |
$str is not valid UTF-8 (after any encoding conversion). |
EncodingConversionException |
iconv / mbstring fail during UTF-8 conversion. |
Esc::esc('plain', 'js'); // plain
Esc::esc('abc,XYZ._0', 'js'); // abc,XYZ._0Esc::esc(' ', 'js'); // \x20
Esc::esc('"', 'js'); // \x22
Esc::esc('/', 'js'); // \x2F
Esc::esc('<', 'js'); // \x3C
Esc::esc('\\', 'js'); // \x5C$untrusted = '"; alert(1); var x="';
Esc::esc($untrusted, 'js');
// \x22\x3B\x20alert\x281\x29\x3B\x20var\x20x\x3D\x22Pasted inside a template:
<script>
var foo = "<?= Esc::esc($untrusted, 'js') ?>";
</script>Browser sees one continuous string literal — the attacker's "; cannot break out.
Esc::esc('ş', 'js'); // ş
Esc::esc('Türkçe', 'js'); // TürkçeEsc::esc('🚀', 'js'); // 🚀This is correct UTF-16 surrogate-pair encoding (high D83D, low DE80) for U+1F680 ROCKET. JavaScript engines decode it back to the single code point.
Esc::esc('</script>', 'js'); // \x3C\x2Fscript\x3EThe < and / become hex escapes, so even if the attacker tries to inject a closing tag the resulting JS source still parses as a string.
Esc::esc('', 'js'); // ''
Esc::esc('98765', 'js'); // 98765| Location | Why | Use instead |
|---|---|---|
| JSON output | JSON has its own well-defined serialisation; escJs is for inline embedding inside a string literal. |
json_encode($value, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT) |
<script type="application/json">…</script> |
That block is JSON, not inline JavaScript. |
json_encode(...) as above |
| Building an identifier / keyword / property name |
escJs is designed for values. Don't paste user input into a variable name or a property accessor. |
Hardcode the identifier or use a fixed lookup table |
| The middle of a template literal (backticks) |
escJs does not escape ${...} interpolation syntax. |
Use a regular string literal ""
|
Inline event handler attribute (onclick="") |
You need both JS escaping (inside the handler) and HTML attribute escaping (around it). |
escJs then escHtmlAttr on the result |
Same as the attribute context — the matcher needs to address full code points, which requires well-formed UTF-8. See Encodings.
-
HTML attribute context — for the surrounding
on*attribute - Security Notes
- FAQ → JSON vs. JS escaping
- API Reference →
escJs
Getting Started
Entry Points
Output Contexts
Reference
Production
Migration & Help