Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
clintonium-119 opened this issue Dec 6, 2019 · 7 comments

Comments

@clintonium-119
Copy link

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:
ajv-validator/ajv#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?

@josundt
Copy link

josundt commented Jan 1, 2020

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.

@clintonium-119
Copy link
Author

@icebob Do you have any thoughts on this?

@icebob
Copy link
Owner

icebob commented Jan 13, 2020

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

@clintonium-119
Copy link
Author

clintonium-119 commented Jan 13, 2020

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.

@maxehhh
Copy link

maxehhh commented Oct 3, 2022

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.

@caracal7
Copy link

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 fastest-validator@1.17.0 and Cloudflare ((

@icebob
Copy link
Owner

icebob commented Oct 1, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants