This document collects quirks, odd behaviors, and security-relevant details in JavaScript useful for VAPT engineers.
throw/1/;
throw /1/;- The
/can be parsed as division or as the start of a regex literal. - Context matters:
throw/1/is parsed asthrow (/1/)(a regex).
return
{
foo: 1
};- Returns
undefinedbecause JS inserts;afterreturn.
[] + [] // ""
[] + {} // "[object Object]"
{} + [] // 0
null == 0 // false
null >= 0 // true- Comparisons and addition behave inconsistently.
eval('alert\x281\x29'); // Hex escape
eval('alert\u00281\u0029'); // Unicode escape
eval('alert\101') // Octal escape
eval('alert(0b1)') // Binary literal
eval('alert(49)') // Decimal char code
eval('al' + 'ert(1)') // String split obfuscation- Obfuscation possible using hex, octal, binary, decimal, unicode escapes.
- Mostly works inside strings, but can influence code generation.
eval("alert(1)")setTimeout("alert(1)")setInterval("alert(1)")new Function("alert(1)")()import('data:text/javascript,alert(1)')
throw/**/1;- Block comments
/*...*/can appear almost anywhere tokens are separated.
var a = '</script><img src=x onerror=alert(1)>';- Injecting HTML inside a script can break out of
<script>context.
\u0061lert(1); // 'a' in unicode
alert\u0028 1 ) // '(' encoded- Obfuscates payloads for bypassing filters.
with({a:1, b:2}){
console.log(a+b);
}- Dynamically injects variables into scope.
- Considered harmful, still supported.
[,,,].length // 3 (holes in arrays)
{a:1, a:2} // {a:2} (duplicate keys overwrite)({}).__proto__.evil = 1;- Modifies global object prototypes.
- Security-sensitive in JS apps.
NaN === NaN // false
isNaN('abc') // trueNaNis never equal to itself.
(function(){ console.log(this); })(); // window (non-strict)
(function(){ 'use strict'; console.log(this); })(); // undefined!![] // true
!!"0" // true
!!0 // false{}; // empty block statement
{}+[]; // NaN (block followed by expression)
({}); // empty object literal{}can be parsed as a code block or as an object literal depending on context.- Leading
(often forces object interpretation.
{} // Valid empty block
{ foo: 1 } // Block containing a labeled statement (NOT an object!)- Empty
{}is valid but meaningless. { foo: 1 }is treated as a block with labelfoo, not an object.
{label: 123}- Parsed as a block with a label named
label, followed by an expression. - Confusingly looks like an object literal but isn’t.
try {
throw 1,2,3;
} catch(e) {
console.log(e); // 3
}- throw accepts only a single expression.
- The comma operator evaluates each operand and returns the last one.
- throw 1,2,3 is equivalent to throw (1,2,3), which evaluates to throw 3.
✅ Summary for VAPT
- Focus on quirks that allow obfuscation, evasion, and unexpected execution.
- Key vectors: eval-like functions, encoding tricks, regex vs division, comment separators, automatic semicolon insertion,
{}ambiguity, prototype manipulation, comma operator behvious and label/block confusion.