Project

Profile

Help

Use of eval() function

Added by Jan-Paul van der Velden about 7 years ago

Our Apache webserver configuration is hardened and doesn't accept that javascript uses the eval() function (for obvious reasons... )

We can see that it is used like this: @ /* A stub for the dynamic XPath functions - the code is loaded only if it is required */ var XPath = function () { function load() { var content = SaxonJS.getPlatform().readResource("lib/xpath/XPathJS.min.js"); content += "XPath;"; /*jslint evil: true */ SaxonJS.XPath = eval(content); }

    return {
        parse: function () {
            load();
            return SaxonJS.XPath.parse.apply(null,arguments);
        },
        compile: function () {
            load();
            return SaxonJS.XPath.compile.apply(null,arguments);
        },
        evaluate: function () {
            load();
            return SaxonJS.XPath.evaluate.apply(null,arguments);
        },
        evaluateXDM: function () {
            load();
            return SaxonJS.XPath.evaluateXDM.apply(null,arguments);
        },
        /* This is used in QT3tests to side-effect components of the static context */
        setStaticContext: function () {
            load();
            return SaxonJS.XPath.setStaticContext.apply(null,arguments);
        }
    };
}
();@

What's the purpose of XPathJS.min.js? We don't have it in our configuration and it doesn't seem to impact the functionality.


Replies (8)

Please register to reply

RE: Use of eval() function - Added by Michael Kay about 7 years ago

XPath.min.js is there to support the xsl:evaluate instruction. It contains an XPath parser which generates an SEF tree representing a compiled XPath expression, which it then executes.

I'll leave John Lumley to address the eval() issue.

RE: Use of eval() function - Added by John Lumley about 7 years ago

As Mike said @XPath.min.js@ is only used to support dynamic XPath evaluation - either in the @xsl:evaluate@ instruction within an XSLT transform or using the @XPath.evaluate()@ JavaScript API. Details are described in http://www.saxonica.com/saxon-js/documentation/index.html#!conformance/dynamic-xpath and http://www.saxonica.com/saxon-js/documentation/index.html#!api/xpathEvaluate.

The code is loaded dynamically as i) it is sizeable (~210kB compared to the rest of SaxonJS being ~220kB) and ii) used comparitively rarely. The arrangement we made was to load dynamically on the first call to any of the accessing functions, so no specific additional declarations or scripts were required from the user. As you have found out, if you don't use @xsl:evaluate@ in your stylesheets, forbidding this dynamic load doesn't impact your functionality. (There are other support features we are adding, such as accumulators, which could also be considered 'optional' - we'll be looking simlarly at means of dynamic loading to keep the initial 'most common' SaxonJS loading footprint small.)

We chose to use @eval()@ as it appeared simplest, and that anyone using dynamic evaluation was was already in the same sort of 'evaluation of external content risk' environment.

If you do wish to use dynamic evaluation, but don't wish to involve the use of JavaScript @eval()@, there are I think at least two possible options:

  • We can very easily supply a 'full' version of SaxonJS where XPath is already incorporated fully - this is the one we use for debugging.
  • It may be possible to use techniques where we add a new @<script>@ child dynamically to the invoking HTML page which adds the XPath library via a normal @@src@ pointer. Of course this has a side effect of altering the HTML page, albeit in the 'non-content' @@ section.

RE: Use of eval() function - Added by Michael Kay about 7 years ago

John:

In all other cases where we do dynamic evaluation of Javascript, we use "new Function()", which is generally considered a bit safer.

However, I have to say I don't quite understand the issue. How and why does an Apache web server configuration affect what Javascript code is allowed to execute on the client?

RE: Use of eval() function - Added by Anonymous about 7 years ago

Apache doesn't affect the code. The browser affects the code.

Apache sends (header) instructions to the browser instructing it to prevent the execution of unsafe code. These Content Security Policy (CSP) headers help in reducing the risks of content injection (like cross-site scripts).

There is more information on https://w3c.github.io/webappsec-csp/ and https://w3c.github.io/webappsec-csp/#directive-script-src

(disclaimer: I'm not a security expert)

RE: Use of eval() function - Added by Michael Kay about 7 years ago

Thanks for those links.

Since the "unsafe-eval" directive also blocks Function(), I'm afraid this looks like a non-starter. For performance we include Javascript code fragments in the SEF file, and we need some kind of dynamic execution capability to execute these.

I guess we could theoretically package all of these fragments as functions in a generated Javascript file and have the SEF file contain the function names, but that's terribly disruptive to the current design.

RE: Use of eval() function - Added by Michael Kay about 7 years ago

Except that looking more carefully, there may be ways around this: see .

  1. Usage of "'strict-dynamic'"

We'll need to study this.

RE: Use of eval() function - Added by Anonymous about 7 years ago

When I look at the SaxonJS.js code the SaxonJS.Xpath.*** methods are only an interface for using the Xpath.js methods. My bold suggestion would be to use Xpath.js directly if it has no further relation to the other SaxonJS.js code (seperation of concerns).

Do I understand this correctly?

RE: Use of eval() function - Added by John Lumley about 7 years ago

As the XPath module uses many features of Saxon-JS, not least to evaluate the generated SEF, and in the case of @xsl:evaluate@ they are intimately tied together to execute the instruction, complete separation isn't possible. (Intepretation of the SEF @evaluate@ expression involves invocation of @SaxonJS.XPath.evaluateXDM()@.)

If we did separate them you'd have the problem that what 'scripts' need to be loaded depends upon whether the XSLT from which the SEF was generated contained @xsl:evaluate@ or not, which takes us back to the dynamic loading issue.

I'll explore the option of @<script>@ loading I hinted at earlier - which might give an alternative when implemented along the lines suggested in https://w3c.github.io/webappsec-csp/#strict-dynamic-usage

Meanwhile we certainly can generate very easily indeed a 'total-feature' SaxonJS.js which contains XPath and does not use @eval()@ at all, though as Mike points out @new Function()@ with SEF-sourced bodies is also used in several places, most notably in axis searching resolution.

    (1-8/8)

    Please register to reply