After consulting MDN for the referrer-policy and Googling, DuckDucking and StackOverlow-searching, maybe you can help me with this rather simple (yet illusive) issue?
This is part of an elaborate set of security checks, in this case deciding if the client has access to a file requested FUBU (for us by us).
This will not work if the referer is missing, but when JavaScript issues a request for a specified worker - the referer (request-header) is indeed missing.
Referrer-Policy: same-origin
for EVERY requestAccess-Control-Allow-Headers: x-requested-with
- in response to EVERY request.How can I find out if a request was made for a JS worker file, or just FORCE the HTTP mechanism to behave like it should?
Since there "seems" to be no way to do this in a "good" way, one could always apply a lil creativity to achieve a specific outcome.
Just to recap:
Worker
invocation, or automaticallyWorker
URL upon invocation could be helpful for automatic handlingHere is a wrapper that can be used to "hijack" some class invocations or methods:
const hijack = function(driver,victim,jacker)
{
if(((typeof driver)=='string')&&!victim){return this.plan[driver]}; // recap
if(victim in this.plan){return}; // only jack once? .. less cruel
this.plan[victim]={victim:driver[victim],jacker:jacker}; // plan the heist
let con = {enumerable:false,configurable:false,writable:false,value:function()
{
let car=hijack((this.mask||this.name||this.constructor.name)); let m=this.mask;
let arg=car.jacker.apply(null,arguments); if(!Array.isArray(arg)){arg=[arg]};
if(!m){return new (Function.prototype.bind.apply(car.victim,[null].concat(arg)))()}
else{return car.victim.apply(this,arg)};
}};
try{con.value.prototype = Object.create(driver[victim].prototype)} // blend in
catch(oops){Object.defineProperty(driver,'mask',{value:victim});}; // recover
Object.defineProperty(driver,victim,con);
}.bind({plan:{}});
... nail meets hammer
driver
~ the object that contains the target function/methodvictim
~ the name of the function/method that will be interceptedjacker
~ a callback-function -which is used to relay/change argumentsvictim
, but this can be extended for multiple intercepts; either by "chain-relay" (callback array) or "event-dispatcher + event-listener combo(s)".Specific to the question:
hijack(window,'Worker',function(arg){return `${arg}?worker=true`});
To address the security concerns in the comments, an api-key could be useful; so if some string
was passed to the running instance (browser or server) that is unique to the current session (or client), it could suffice, for example:
hijack(window,'Worker',function(arg){return `${arg}?worker=${window.ApiKey}`});
.. where ApiKey
was defined globally as a string
, but it can also be the result of a function-call -which gets it from a cookie, or whichever.
This can also be used to enhance security. If you are concerned about XHR requests made from devtools or even worse: eval() -then you can use this hijack
to intercept those calls/invocations globally.
For example:
hijack(URL,'createObjectURL',function(arg){console.log(arg); return `whatever`});
If you plan to use this as security tool, then it needs some TLC with a dash of "call-stack back-trace", a "mutation-observer" .. and a pinch of (dark) matter (:
disclaimer
nobody got hurt during this exercise .. the victim turned out okay .. use at your own discretion