fastest-validator icon indicating copy to clipboard operation
fastest-validator copied to clipboard

Provide a way to pre-compile the object checkers to run without 'unsafe-eval' CSP directive

Open clintonium-119 opened this issue 5 years ago • 7 comments
trafficstars

I'm trying to figure out if there's a way to run this without having to include the unsafe-eval directive in our Content Security Policy's script-src

The issue stems from the New Function(....) call(s). I understand why this is necessary to compile the object checkers, but I was hoping to find a way to generate the compiled checker functions ahead of runtime in our build process, so that I could include them as inline scripts in our build templates, and allow them to pass our CSP using either nonces or hashes.

The AVJ validation library has this capability offered via a CLI to address this issue: https://github.com/epoberezkin/ajv/issues/406

I was hoping to find a way to accomplish the same thing here, but I'm not sure if: a) it would be something you'd be interested in accommodating b) it's technically feasible -- looking at the code, I think it could be done, but I'm not certain.

I can of course get it to run without pre-compiling (i.e. with v.validate), but we have a lot of data passing through and the performance hit is much too high to be feasible for us.

Any thoughts or ideas?

clintonium-119 avatar Dec 06 '19 17:12 clintonium-119

An alternative to using the Function constructor is to use dynamic import() of a dataURI containing the source code.

This will require Content-Security-Policy: script-src data:, but not Content-Security-Policy: script-src 'unsafe-eval'

This technique requires Promise support/polyfill and import() support in browser/transpiler/bundler.

ajv probably probably wants no Promise or import() support dependencies, I therefore think that ajv could let the consumer provide an alternate function compiler function through Ajv options or in an alternate compile function. The compile function needs to be "async" with a callback signature.

Example:

function compileFunctionDefault(args, body, callback) {
    callback(new Function(...args, body));
}

function compileFunctionUsingDataUriImport(args, body, callback) {
    var fnSrc = `export default function(${args.join(", ")}) { ${body} }`;
    var encodedSrc = encodeURIComponent(fnSrc);
    const dataUri = 'data:text/javascript;charset=utf-8,' +  encodedSrc;
    import(dataUri).then(mod => {
        callback(mod.default);
    });
}

var fnArgs = ['message'];
var fnBody = 'alert(message);';

compileFunctionDefault(fnArgs, fnBody, showMessage => {
    showMessage('This requires "Content-Security-Policy: script-src \'unsafe-eval\'"');
});

compileFunctionUsingDataUriImport(fnArgs, fnBody, showMessage => {
    showMessage('This requires "Content-Security-Policy: script-src data:"');
});

The example above works in modern browsers...

For web applications today, 'unsafe-eval' is becoming unacceptable. I encourage you to consider my proposal.

josundt avatar Jan 01 '20 10:01 josundt

@icebob Do you have any thoughts on this?

clintonium-119 avatar Jan 08 '20 16:01 clintonium-119

I have no idea how I can add it. So, PR is welcome :)

icebob avatar Jan 13 '20 08:01 icebob

I'm not sure that I'd want to allow script-src: 'data:' either. It would be better than unsafe-eval, but for the application I'm working on we need to keep a pretty tight CSP.

For others in my position still wanting to use this library and keep a strict CSP, I was able to downgrade to 0.6.10 (the build before the new Function(....) performance optimizations were added), and all is well. I had to rewrite a couple of custom validators, but it wasn't too bad, and the performance is still very good for our datasets.

Appreciate your work on this, @icebob. Very nice library. I wish I had time to contribute a PR to introduce a pre-compile cli, but we will be moving the validation server-side relatively soon, and so this is more of a temporary use-case for us.

clintonium-119 avatar Jan 13 '20 14:01 clintonium-119

I'm not sure that I'd want to allow script-src: 'data:' either. It would be better than unsafe-eval, but for the application I'm working on we need to keep a pretty tight CSP.

For others in my position still wanting to use this library and keep a strict CSP, I was able to downgrade to 0.6.10 (the build before the new Function(....) performance optimizations were added), and all is well. I had to rewrite a couple of custom validators, but it wasn't too bad, and the performance is still very good for our datasets.

Appreciate your work on this, @icebob. Very nice library. I wish I had time to contribute a PR to introduce a pre-compile cli, but we will be moving the validation server-side relatively soon, and so this is more of a temporary use-case for us.

I'm using workers from Cloudflare and get the exception of "Code generation from strings disallowed for this context" using latest version, downgrading to the one clintonium recommends fixed it.

maxehhh avatar Oct 03 '22 21:10 maxehhh

I'm using workers from Cloudflare and get the exception of "Code generation from strings disallowed for this context" using latest version, downgrading to the one clintonium recommends fixed it.

I have the same issue with [email protected] and Cloudflare ((

caracal7 avatar Sep 27 '23 11:09 caracal7

I'm waiting for PR because I have no idea how implementing it correctly. So instead of additional requirement comments please provide a draft PR with a solution if you have. Thanks

icebob avatar Oct 01 '23 09:10 icebob