New Safari XSS Vulnerability Exploits JavaScript Error Handling to Run Arbitrary Code
Cross-site scripting (XSS) remains one of the most persistent threats in web security, but most discussions focus on traditional vectors.
A lesser-known but intriguing avenue is exploiting JavaScript TypeError messages in Safari to achieve XSS.
This technique leverages how Safari constructs error messages, specifically failing to escape embedded quotes, which can allow for code injection and execution.
The core of this attack involves forcing a TypeError by misusing the JavaScript new operator with a crafted string. For example:
javascriptnew 'foo"bar'
// TypeError: "foo"bar" is not a constructor
Safari converts single quotes to double quotes in the error message but does not escape embedded double quotes.
This creates an opportunity: by injecting a payload such as ‘foo”-alert(1)//’The resulting TypeError message becomes:
javascriptTypeError: "foo"-alert(1)//" is not a constructor
If this message is passed to an eval
function, the payload executes, triggering an alert box.
Unlike syntax errors, TypeErrors do not halt JavaScript execution, making them exploitable in this context.
Payload Delivery:
The next challenge is triggering the vulnerable code path.
One approach is to set the global onerror handler to eval, ensuring any error message, such as our crafted TypeError, gets evaluated as JavaScript:
javascriptonerror = eval;
new 'foo"-alert(1)//';
Here, onerror
is assigned to eval
, so when the TypeError is thrown, its message (containing the XSS payload) is evaluated, executing arbitrary JavaScript.
This technique can be extended to other string sources, such as window.name
, which is often used for cross-window communication.
By storing the payload in window.name and then triggering the error, the exploit can persist across navigation, although Safari resets window.name on navigation, unless workarounds like the target
attribute or window.open
are used.
The following table summarizes the key elements of the attack:
Step | Code Example | Purpose |
---|---|---|
Craft TypeError payload | new 'foo"-alert(1)//' |
Triggers TypeError with payload |
Assign onerror to eval | onerror = eval; |
Evaluates error messages as code |
Store payload in window.name | window.name="foo"-alert(1)//"; |
Cross-window payload persistence |
Trigger error from name | new window.name; |
Executes payload from window.name |
Mitigation and Broader Implications
This exploitation method highlights the importance of robust error handling and proper encoding.
While Safari has patched several related vulnerabilities over the years, such as CVE-2016-4618, which allowed arbitrary script injection via crafted web content—developers must remain vigilant.
Key mitigations include:
- Never assign
onerror
toeval
or similar functions. - Always encode and sanitize user-controlled strings, especially when reflected in error messages or logs.
- Avoid using untrusted data as JavaScript constructor arguments.
The XSS Filter Evasion Cheat Sheet from OWASP provides numerous examples of how attackers can bypass naive filters, including leveraging error objects and event handlers to execute payloads.
Here are a few advanced payloads:
xml
These techniques demonstrate that even seemingly innocuous JavaScript errors can become vectors for sophisticated attacks if not properly managed.
As browsers evolve, so too do attacker methodologies—underscoring the need for ongoing vigilance and secure coding practices in web development.