I want my app with a REST API to be accessible in different flavors:
- From the same domain (use normal AJAX request here)
- From another domain via script attached by site owner (CORS)
- From another domain via userscript (GM_xmlhttpRequest (?))
I want to limit the list of sites for my app to be accessible from by a whitelist.
I know how to do it with CORS but I'm not sure if it works with GM_xmlhttpRequest the same way since GM_xmlhttpRequest does not require the Origin header to be sent back from a server.
I don't care for a client but I still need to check on a server from which site the request was sent and answer with something like {response:"site not supported"} if it isn't in a whitelist.
So, when I run a userscript on some webpage and make a GM_xmlhttpRequest, can the server detect the origin?
You cannot use the
Originheader to reliably restrict access by userscripts to your API.By default,
GM_xmlhttpRequest()Doc does not send theOriginheader at all. Nor doesGM_xmlhttpRequestblock cross-site requests; that is the main reason thatGM_xmlhttpRequestexists.Also, for Greasemonkey (Firefox) and Tampermonkey (Chrome),
GM_xmlhttpRequestdoes not send therefererheader, by default.However, both headers can be overridden to be whatever the script-writer wants.
Here is a demo script that spoofs both headers (use a packet sniffer to see for yourself):
A plain Chrome userscript is not so kind to the script developer. Native Chrome userscripts never send the
Originheader and always send the current page as thereferer.If you try to spoof either of these headers, the console will show errors like:
This is one more reason to use Tampermonkey for your Chrome userscripts.