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

Undefined handlers cause error when unsafe-eval is restricted by the CSP header #49

Open
KarsonAlford opened this issue Mar 20, 2019 · 9 comments · May be fixed by #48
Open

Undefined handlers cause error when unsafe-eval is restricted by the CSP header #49

KarsonAlford opened this issue Mar 20, 2019 · 9 comments · May be fixed by #48

Comments

@KarsonAlford
Copy link

Undefined handlers (OnBegin, OnSuccess, etc.) cause a browser evaluation error when unsafe-eval is restricted by the CSP header.

If you modify all of the text in the handlers to functions instead of JavaScript code then those handlers that contain functions will no longer be blocked by the browser (window.stop [function] vs window.stop() [code needing evaluation]). However, the issue is that the handlers that are left blank will be blocked by the browser and cause an error.

Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive:

Related to Issue #23.

@KarsonAlford
Copy link
Author

KarsonAlford commented Mar 20, 2019

Explanation:
The getFunction method first tries to find the function in the DOM and falls back to eval via Function.constructor. Currently if one of the handlers (OnBegin, OnSuccess, etc.) is not defined then null is passed into getFunction which is evaluated and a function created that returns null.

Possible Fix:

function getFunction(code, argNames) {
    if (!code) return function() { return null; };

Current Options:
Option 1) Add a NOOP function for all the handlers that you are not using.

window.noop = function() { return null; };

OnBegin="noop"
OnSuccess="noop"

Option 2) Replace Function.apply so that the eval is not possible. Inspired by this blog post.

Function.apply = function (element, args) {
    if (args && args.length && args.length !== 0) {
        var code = args[args.length - 1];
        if (code) {
            console.log('JavaScript evaluation prevented - ' + code);
        }
    }
    return function () { return null; };
};

@AdamWillden
Copy link

@KarsonAlford I completely agree and cannot understand why eval is used even in cases where there's nothing to evaluate.

Please @mkArtakMSFT, @javiercn reconsider your stance on this. There's no need to depreciate existing features as was described previously in order to support the avoidance of eval.

@jumpingjackson
Copy link

jumpingjackson commented Jul 9, 2020

I tried applying the changes in #48 to my copy, but i still get CSP violation.. Its getting past the if (!code) return function() { return null; }; check.

@KarsonAlford
Copy link
Author

Can you post your example?

This fix is to stop empty handlers causing a CSP violation. If you are getting past !code then I assume you have something in a handler that is not a function in the DOM and therefore is being evaluated.

@jumpingjackson
Copy link

jumpingjackson commented Jul 10, 2020 via email

@calaluis
Copy link

Explanation:
The getFunction method first tries to find the function in the DOM and falls back to eval via Function.constructor. Currently if one of the handlers (OnBegin, OnSuccess, etc.) is not defined then null is passed into getFunction which is evaluated and a function created that returns null.

Possible Fix:

function getFunction(code, argNames) {
    if (!code) return function() { return null; };

Current Options:
Option 1) Add a NOOP function for all the handlers that you are not using.

window.noop = function() { return null; };

OnBegin="noop"
OnSuccess="noop"

Option 2) Replace Function.apply so that the eval is not possible. Inspired by this blog post.

Function.apply = function (element, args) {
    if (args && args.length && args.length !== 0) {
        var code = args[args.length - 1];
        if (code) {
            console.log('JavaScript evaluation prevented - ' + code);
        }
    }
    return function () { return null; };
};

Hello dear,

First of all, thanks to find a possible solution to this big problem, for an extremely used library in ASP.NET MVC.

I can inform you that option 2 has been implemented, within which it throws the following CSP error towards the Jquery library:

image

Stay tuned to your comments.

@KarsonAlford
Copy link
Author

See the JS that I am using below. It also prevents $.globalEval which I didn't document in my original post.

I hope this helps.

disableEval.js

(function ($) {
    "use strict";

    // replace apply for Function.constructor
    Function.apply = function (element, args) {
        if (args && args.length && args.length !== 0) {
            var code = args[args.length - 1];
            if (code) {
                console.log('JavaScript evaluation prevented - ' + code);
            }
        }

        return function () { return null; };
    };

    $(function () {
        $.globalEval = function (code) { console.log('jQuery evaluation prevented - ' + code); };
    });
}(jQuery));

@calaluis
Copy link

Thank you very much @KarsonAlford , it worked perfect.

Now to investigate other libraries that also give problems with the CSP, such as the BlockUI.

@KAJOOSH
Copy link

KAJOOSH commented Sep 5, 2023

After a few years, don't you want to think fundamentally to solve this problem?

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

Successfully merging a pull request may close this issue.

5 participants