Skip to content

Security warning: avoid using function constructor. #897

Closed

Description

@feugy

I recently discovered that one of plotly.js's dependency is using Function constructor.
Unfortunately, I can't tell exactly which one, but the code doesn't seems to belong to plotly itself.

Here is Chrome's error message:

plotly.js:74222Uncaught 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: "script-src 'self'
 www.google-analytics.com ajax.googleapis.com 'nonce-67df8dace6ea7feb57cab73e41ebe0c7'".

makeOp  @   plotly.js:74222
(anonymous function)    @   plotly.js:74244
455.cwise-compiler  @   plotly.js:74271
s   @   plotly.js:7
(anonymous function)    @   plotly.js:7
129.ndarray @   plotly.js:25687
s   @   plotly.js:7
(anonymous function)    @   plotly.js:7
138../lib/shaders   @   plotly.js:27330
s   @   plotly.js:7
(anonymous function)    @   plotly.js:7
798.../../constants/gl3d_dashes @   plotly.js:127609
s   @   plotly.js:7
(anonymous function)    @   plotly.js:7
800.../../constants/gl_markers  @   plotly.js:128154
s   @   plotly.js:7
(anonymous function)    @   plotly.js:7
15.../src/traces/scatter3d  @   plotly.js:355
s   @   plotly.js:7
(anonymous function)    @   plotly.js:7
12../bar    @   plotly.js:312
s   @   plotly.js:7
e   @   plotly.js:7
(anonymous function)    @   plotly.js:7
a   @   plotly.js:7
(anonymous function)    @   plotly.js:7
__webpack_require__ @   bootstrap 08e5224…:585
fn  @   bootstrap 08e5224…:109
(anonymous function)    @   svg-to-png.js:2
__webpack_require__ @   bootstrap 08e5224…:585
fn  @   bootstrap 08e5224…:109
(anonymous function)    @   commons.js:36658
__webpack_require__ @   bootstrap 08e5224…:585
fn  @   bootstrap 08e5224…:109
(anonymous function)    @   index.js:1
__webpack_require__ @   bootstrap 08e5224…:585
fn  @   bootstrap 08e5224…:109
(anonymous function)    @   bootstrap.js:9
__webpack_require__ @   bootstrap 08e5224…:585
fn  @   bootstrap 08e5224…:109
(anonymous function)    @   index.js:3
__webpack_require__ @   bootstrap 08e5224…:585
fn  @   bootstrap 08e5224…:109
(anonymous function)    @   index.js:8
__webpack_require__ @   bootstrap 08e5224…:585
webpackJsonpCallback    @   bootstrap 08e5224…:21
(anonymous function)    @   index.js:1

Function constructor is considered by browser's CSP as an equivalent of eval.
Therefore, we can't setup a good Content Security Policy, unless we allow 'unsafe-eval' which is a whole in the policy itself.

It is possible to identify the faulty dependency, and maybe provide a workaround ?

Activity

  1. rreusser commented on Sep 2, 2016

    @rreusser
    Contributor

    I think this is the line: https://github.com/scijs/cwise-compiler/blob/master/lib/compile.js#L351

    cwise is a library that performs operations on ndarrays. It doesn't look like plotly uses the cwise browserify transform when bundling plotly.js, but I believe even the transformed version that does the parsing ahead of time still compiles an optimized version (i.e. new Function) at runtime.

    Long story short, this is pretty central to what cwise does, so I'm not totally sure of a good workaround, unless there's a way to short-circuit the optimization and just perform naive operations on data.

    Edit: more precisely, this looks like it might be coming from ndarray-ops, which is already transformed, but the problem remains the same. Looks like it's coming from here. That wouldn't be too hard to rewrite naively, but I'd be surprised if cwise didn't creep in somewhere else in the dependencies.

  2. etpinard commented on Sep 2, 2016

    @etpinard
    Contributor

    It doesn't look like plotly uses the cwise browserify transform when bundling plotly.js,

    The plotly build step doesn't explicitly list the cwise transform, but several of our dependencies have cwise listed in their respective package.json namely ndarray-fill, ndarray-wrap and gl-select-static (ref this script).

  3. willemx commented on Apr 12, 2017

    @willemx

    I'm also running into this problem. Can't run my (Meteor) app because of this.
    Is there a work-around maybe?

  4. jacobq commented on Feb 27, 2018

    @jacobq

    When I tried to bring plotly.js into my Electron application (via ember-plotly-shim) it triggers a security warning. In fact, since I have a set a Content-Security-Policy per the recommendations, it does not run at all.

    Would someone be willing to write some / point to some documentation that describes how to incorporate plotly w/o using a pipeline that evaluates strings as code?

    unsafe-string-eval

  5. fxfilmxf commented on Mar 9, 2018

    @fxfilmxf

    Still seeing this as well. Hasn't been addressed at all.

  6. etpinard commented on Mar 9, 2018

    @etpinard
    Contributor

    Nothing has changed since #897 (comment), so yes this hasn't been addressed at all 😱

    The problematic cwise transform is only used in gl3d and gl2d (excluding scattergl), so using one of the partial bundles that don't include these trace types would solve this issue. Better yet, bundling plotly.js yourself may do the trick.

  7. fxfilmxf commented on Mar 9, 2018

    @fxfilmxf

    Thanks for the advice! I'll take a look at that.

  8. jtal commented on Nov 6, 2018

    @jtal

    Does anyone have the CSP header they've used to keep security as tight as possible but still use plotly?

  9. jacobq commented on Nov 7, 2018

    @jacobq

    @jtal

    Does anyone have the CSP header they've used to keep security as tight as possible but still use plotly?

    I recommend starting with the strictest options and gradually relaxing restrictions until your application functions properly. There may be other parts of your work that won't work when fully restricted. As an example only, here is one I have used (inside of an electron app):
    default-src 'none'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self'; img-src 'self' 'data:'; style-src 'self' 'unsafe-inline'

    See MDN

  10. anders-kiaer commented on Feb 12, 2020

    @anders-kiaer

    Looks like the direct plotly.js dependencies today that make plotly.js dependent on cwise are:

    Does anyone know if it is feasible for plotly.js to go away from these dependencies (any alternatives?) and/or modify the dependencies themselves to not use cwise?

    The unsafe-eval requirement is unfortunately currently stopping us from being allowed to use plotly.js's variant of parallell coordinates, as it appears to be part of the gl2d bundle, which then looks to be indirectly requiring cwise, ref. #897 (comment).

  11. etpinard commented on Feb 12, 2020

    @etpinard
    Contributor

    @anders-kiaer you may be interested in https://www.npmjs.com/package/plotly.js-gl2d-dist, you can install it using

    npm install plotly.js-gl2d-dist
    

    which has no dependencies.

  12. anders-kiaer commented on Feb 12, 2020

    @anders-kiaer

    Thanks @etpinard 🙂 Hmm, not sure if I understand, isn't the cwise dependency bundled into the gl2d dist? I tried using the dist from npm install plotly.js-gl2d-dist, and also what I think is the CDN equivalent, and got the same CSP block without 'unsafe-eval'. Tested using this Dash snippet:

    import dash
    import dash_html_components as html
    from flask_talisman import Talisman
    
    app = dash.Dash(
        __name__, external_scripts=["https://cdn.plot.ly/plotly-gl2d-latest.min.js"]
    )
    
    
    CSP = {
        "default-src": "'self'",
        "script-src": [
            "'self'",
            "https://cdn.plot.ly",
            # "'unsafe-eval'",
            "'sha256-jZlsGVOhUAIcH+4PVs7QuGZkthRMgvT2n0ilH6/zTM0='",
        ],
        "style-src": ["'self'", "'unsafe-inline'"],
    }
    
    Talisman(app.server, content_security_policy=CSP, force_https=False)
    
    app.layout = html.Span("Hello Dash!")
    
    if __name__ == "__main__":
        app.run_server()

    which when looking at the browser console gives a

    EvalError: call to Function() blocked by CSP
    

    unless 'unsafe-eval' is added. Searching through plotly-gl2d.js gives me 18 hits on Function(. The first hit looks to come from this line.

  13. etpinard commented on Feb 12, 2020

    @etpinard
    Contributor

    My mistake. I thought you were worried about the "unsafe-eval" behavior of cwise when bundling your own custom bundle, not in the browser runtime.

    Unfortunately, there's no easy way for us to simply replace cwise. This package can improve performance by a large amount.

  14. etpinard commented on Feb 12, 2020

    @etpinard
    Contributor

    But, the basic, cartesian, geo, mapbox and finance partial bundles should be fine.

    That is, bundles that include trace types other than gl3d, gl2d, scattergl and splom should pass the "unsafe-eval" checks.

  15. 11 remaining items

  16. archmoj commented on Aug 31, 2020

    @archmoj
    Contributor

    Hello @nicolaskruchten ,
    Yes, it was on 1.54.7. We've been trying to embed plotly renderings as one of the rendering "macros" for cryptpad code (https://cryptpad.fr/). Cryptpad aimst at very high security standard and thus requires CSP.
    If we deactivate CSP, then things load.
    If we activate CSP then I get the following having replaced the plotly with the non-minimized version.

        Uncaught EvalError: call to Function() blocked by CSP
        makeOp http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:60786
        [443]</< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:60808
        [443]< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:60835
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        [253]< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:41713
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        [266]< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:44060
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        [1164]< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:190058
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        [1166]< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:190689
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        [36]< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:614
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        [26]< http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:420
        o http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        r http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        <anonymous> http://localhost:3000/lib/plotly-latest.min.js?ver=3.20.1-1596722563915:7
        execCb http://localhost:3001/bower_components/requirejs/require.js?ver=2.3.5:1696
    

    Does it help?

    Paul

    @polx could you please use the unminified version i.e. "plotly-latest.js" instead to re-produce the list?

  17. polx commented on Sep 2, 2020

    @polx

    Sorry @archmoj , it is called plotly-min but is a copy of plotly.js.
    I just downloaded 1.54.7 again and compared and they are equal:
    diff lib/plotly-latest.min.js /tmp/plotly.js-1.54.7/dist/plotly.js is empty (and both have md5 8948b85ca08520fa7ff3718ffe40dd4e).

    paul

  18. jackparmer commented on Sep 10, 2020

    @jackparmer
    Contributor

    This issue has been tagged with NEEDS SPON$OR

    A community PR for this feature would certainly be welcome, but our experience is deeper features like this are difficult to complete without the Plotly maintainers leading the effort.

    Sponsorship range: $45k-$50k

    What Sponsorship includes:

    • Completion of this feature to the Sponsor's satisfaction, in a manner coherent with the rest of the Plotly.js library and API
    • Tests for this feature
    • Long-term support (continued support of this feature in the latest version of Plotly.js)
    • Documentation at plotly.com/javascript
    • Possibility of integrating this feature with Plotly Graphing Libraries (Python, R, F#, Julia, MATLAB, etc)
    • Possibility of integrating this feature with Dash
    • Feature announcement on community.plotly.com with shout out to Sponsor (or can remain anonymous)
    • Gratification of advancing the world's most downloaded, interactive scientific graphing libraries (>50M downloads across supported languages)

    Please include the link to this issue when contacting us to discuss.

  19. nicolaskruchten commented on Oct 6, 2020

    @nicolaskruchten
    Contributor

    Great news: Equinor is generously willing to sponsor $15k of this work if we can find sponsors for the rest! Please let us know if you're able to contribute part of the remaining $30k-$35k and we can get started on this project :)

  20. archmoj commented on Dec 14, 2020

    @archmoj
    Contributor

    Here is the complete list of function constructors and their dependency path from different bundles.

    dependency: d3

    plotly.js@1.58.1
    └── d3@3.5.17
    

    at:

    file: d3/src/dsv/dsv.js
    func: dsv.parse
    line: var a = new Function("d", "return {" + row.map(function(name, i) {
    
    bundle impacted
    basic yes
    cartesian yes
    finance yes
    geo yes
    mapbox yes
    gl2d yes
    gl3d yes

    dependency: es6-promise

    plotly.js@1.58.1
    └── es6-promise@4.2.8
    

    at:

    file: es6-promise/dist/es6-promise.js
    func: attemptVertx
    line: var vertx = Function('return this')().require('vertx');
    

    and

    at:

    file: es6-promise/dist/es6-promise.js
    func: polyfill
    line: local = Function('return this')();
    
    bundle impacted
    basic yes
    cartesian yes
    finance yes
    geo yes
    mapbox yes
    gl2d yes
    gl3d yes

    dependency: binary-search-bounds

    plotly.js@1.58.1
    ├─┬ @plotly/point-cluster@3.1.9
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-contour2d@1.1.7
    │ ├── binary-search-bounds@2.0.4
    │ └─┬ cdt2d@1.0.0
    │   └── binary-search-bounds@2.0.4
    ├─┬ gl-heatmap2d@1.1.0
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-line3d@1.2.1
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-plot2d@1.4.5
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-plot3d@2.4.7
    │ └─┬ 3d-view@2.0.0
    │   └─┬ orbit-camera-controller@4.0.0
    │     └─┬ filtered-vector@1.2.4
    │       └── binary-search-bounds@1.0.0
    ├─┬ gl-scatter3d@1.2.3
    │ └─┬ vectorize-text@3.2.1
    │   └─┬ planar-graph-to-polyline@1.0.5
    │     └─┬ point-in-big-polygon@2.0.0
    │       ├── binary-search-bounds@1.0.0
    │       ├─┬ interval-tree-1d@1.0.3
    │       │ └── binary-search-bounds@1.0.0
    │       └─┬ slab-decomposition@1.0.2
    │         └── binary-search-bounds@1.0.0
    ├─┬ gl-surface3d@1.6.0
    │ └── binary-search-bounds@2.0.4
    └─┬ matrix-camera-controller@2.1.3
      └── binary-search-bounds@1.0.0
    

    at:

    file: binary-search-bounds/search-bounds.js
    func: compileBoundsSearch
    line: var result = new Function([
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: box-intersect

    plotly.js@1.58.1
    └─┬ gl-contour2d@1.1.7
      └─┬ clean-pslg@1.1.2
        └── box-intersect@1.0.2
    

    at:

    func: bruteForcePlanner
    file: box-intersect/lib/brute.js
    line: var proc = new Function(codeStr)
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: cwise-compiler

    plotly.js@1.58.1
    ├─┬ gl-contour2d@1.1.7
    │ └─┬ surface-nets@1.0.2
    │   └─┬ zero-crossings@1.0.1
    │     └── cwise-compiler@1.1.3
    └─┬ gl-surface3d@1.6.0
      ├─┬ ndarray-gradient@1.0.0
      │ └── cwise-compiler@1.1.3
      ├─┬ ndarray-ops@1.2.2
      │ └── cwise-compiler@1.1.3
      └─┬ ndarray-pack@1.2.1
        └── cwise-compiler@1.1.3
    

    at:

    file: cwise-compiler/lib/compile.js
    func: generateCWiseOp
    line: var f = new Function(["function ",loopName,"(", arglist.join(","),"){", code.join("\n"),"} return ", loopName].join(""))
    

    and

    at:

    func: createThunk
    file: cwise-compiler/lib/thunk.js
    line: var thunk = new Function("compile", code.join("\n"))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: gl-shader

    plotly.js@1.58.1
    ├─┬ gl-cone3d@1.5.2
    │ └── gl-shader@4.2.1
    ├─┬ gl-contour2d@1.1.7
    │ └── gl-shader@4.2.1
    ├─┬ gl-error3d@1.0.16
    │ └── gl-shader@4.2.1
    ├─┬ gl-heatmap2d@1.1.0
    │ └── gl-shader@4.2.1
    ├─┬ gl-line3d@1.2.1
    │ └── gl-shader@4.2.1
    ├─┬ gl-mesh3d@2.3.1
    │ └── gl-shader@4.2.1
    ├─┬ gl-plot2d@1.4.5
    │ └── gl-shader@4.2.1
    ├─┬ gl-plot3d@2.4.7
    │ ├─┬ gl-axes3d@1.5.3
    │ │ └── gl-shader@4.2.1
    │ ├── gl-shader@4.2.1
    │ └─┬ gl-spikes3d@1.0.10
    │   └── gl-shader@4.2.1
    ├─┬ gl-pointcloud2d@1.0.3
    │ └── gl-shader@4.2.1
    ├─┬ gl-scatter3d@1.2.3
    │ └── gl-shader@4.2.1
    ├─┬ gl-select-box@1.0.4
    │ └── gl-shader@4.2.1
    └─┬ gl-surface3d@1.6.0
      └── gl-shader@4.2.1
    

    at:

    file: gl-shader/lib/create-uniforms.js
    func: identity
    line: var c = new Function('y', 'return function(){return y}')
    

    and

    at:

    file: gl-shader/lib/create-uniforms.js
    func: makeGetter
    line: var proc = new Function('gl', 'wrapper', 'locations', 'return function(){return gl.getUniform(wrapper.program,locations[' + index + '])}')
    

    and

    at:

    file: gl-shader/lib/create-uniforms.js
    func: makeSetter
    line: var proc = new Function('gl', 'locations', code.join('\n'))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: binary-search-bounds

    plotly.js@1.58.1
    ├─┬ @plotly/point-cluster@3.1.9
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-contour2d@1.1.7
    │ ├── binary-search-bounds@2.0.4
    │ └─┬ cdt2d@1.0.0
    │   └── binary-search-bounds@2.0.4
    ├─┬ gl-heatmap2d@1.1.0
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-line3d@1.2.1
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-plot2d@1.4.5
    │ └── binary-search-bounds@2.0.4
    ├─┬ gl-plot3d@2.4.7
    │ └─┬ 3d-view@2.0.0
    │   └─┬ orbit-camera-controller@4.0.0
    │     └─┬ filtered-vector@1.2.4
    │       └── binary-search-bounds@1.0.0
    ├─┬ gl-scatter3d@1.2.3
    │ └─┬ vectorize-text@3.2.1
    │   └─┬ planar-graph-to-polyline@1.0.5
    │     └─┬ point-in-big-polygon@2.0.0
    │       ├── binary-search-bounds@1.0.0
    │       ├─┬ interval-tree-1d@1.0.3
    │       │ └── binary-search-bounds@1.0.0
    │       └─┬ slab-decomposition@1.0.2
    │         └── binary-search-bounds@1.0.0
    ├─┬ gl-surface3d@1.6.0
    │ └── binary-search-bounds@2.0.4
    └─┬ matrix-camera-controller@2.1.3
      └── binary-search-bounds@1.0.0
    

    at:

    file: binary-search-bounds/search-bounds.js
    func: compileBoundsSearch
    line: var result = new Function([
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: ndarray-extract-contour

    plotly.js@1.58.1
    └─┬ gl-contour2d@1.1.7
      └─┬ surface-nets@1.0.2
        └── ndarray-extract-contour@1.0.1
    

    at:

    file: ndarray-extract-contour/contour.js
    func: compileSurfaceProcedure
    line: var proc = new Function("vertex", "face", "phase", "mallocUint32", "freeUint32", procedureCode)
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: ndarray-ops

    plotly.js@1.58.1
    ├─┬ gl-cone3d@1.5.2
    │ ├─┬ gl-buffer@2.1.2
    │ │ └── ndarray-ops@1.2.2
    │ └─┬ gl-texture2d@2.1.0
    │   └── ndarray-ops@1.2.2
    └─┬ gl-surface3d@1.6.0
      ├── ndarray-ops@1.2.2
      └─┬ ndarray-scratch@1.2.0
        └── ndarray-ops@1.2.2
    

    at:

    file: ndarray-ops/ndarray-ops.js
    func: makeOp
    line: var wrapper = new Function("P", [
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: ndarray

    plotly.js@1.58.1
    ├─┬ gl-cone3d@1.5.2
    │ ├─┬ gl-buffer@2.1.2
    │ │ └── ndarray@1.0.19
    │ ├─┬ gl-texture2d@2.1.0
    │ │ └── ndarray@1.0.19
    │ └── ndarray@1.0.19
    ├─┬ gl-contour2d@1.1.7
    │ └── ndarray@1.0.19
    ├─┬ gl-line3d@1.2.1
    │ └── ndarray@1.0.19
    ├─┬ gl-mesh3d@2.3.1
    │ ├── ndarray@1.0.19
    │ └─┬ simplicial-complex-contour@1.0.2
    │   └── ndarray@1.0.19
    ├─┬ gl-plot2d@1.4.5
    │ └─┬ gl-select-static@2.0.7
    │   └── ndarray@1.0.19
    ├─┬ gl-plot3d@2.4.7
    │ └── ndarray@1.0.19
    ├─┬ gl-scatter3d@1.2.3
    │ └─┬ vectorize-text@3.2.1
    │   └── ndarray@1.0.19
    ├─┬ gl-surface3d@1.6.0
    │ ├── ndarray@1.0.19
    │ ├─┬ ndarray-pack@1.2.1
    │ │ └── ndarray@1.0.19
    │ └─┬ ndarray-scratch@1.2.0
    │   └── ndarray@1.0.19
    └── ndarray@1.0.19
    

    at:

    file: ndarray/ndarray.js
    func: compileConstructor
    line: var procedure = new Function(code)
    

    and

    at:

    file: ndarray/ndarray.js
    func: compileConstructor
    line: var procedure = new Function("TrivialArray", code)
    

    and

    at:

    file: ndarray/ndarray.js
    func: compileConstructor
    line: var procedure = new Function("CTOR_LIST", "ORDER", code.join("\n"))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: robust-in-sphere

    plotly.js@1.58.1
    └─┬ gl-contour2d@1.1.7
      └─┬ cdt2d@1.0.0
        └── robust-in-sphere@1.1.3
    

    at:

    file: robust-in-sphere/in-sphere.js
    line: var proc = new Function("sum", "diff", "prod", "scale", code.join(""))
    func: orientation
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: robust-orientation

    plotly.js@1.58.1
    ├─┬ convex-hull@1.0.3
    │ ├─┬ affine-hull@1.0.0
    │ │ └── robust-orientation@1.1.3
    │ ├─┬ incremental-convex-hull@1.0.1
    │ │ └── robust-orientation@1.1.3
    │ └─┬ monotone-convex-hull-2d@1.0.1
    │   └── robust-orientation@1.1.3
    ├─┬ gl-contour2d@1.1.7
    │ ├─┬ cdt2d@1.0.0
    │ │ └── robust-orientation@1.1.3
    │ └─┬ clean-pslg@1.1.2
    │   └─┬ robust-segment-intersect@1.0.1
    │     └── robust-orientation@1.1.3
    ├─┬ gl-plot3d@2.4.7
    │ └─┬ gl-axes3d@1.5.3
    │   └── robust-orientation@1.1.3
    ├─┬ gl-scatter3d@1.2.3
    │ └─┬ vectorize-text@3.2.1
    │   ├─┬ planar-graph-to-polyline@1.0.5
    │   │ ├─┬ planar-dual@1.0.2
    │   │ │ └─┬ compare-angle@1.0.1
    │   │ │   └── robust-orientation@1.1.3
    │   │ ├─┬ point-in-big-polygon@2.0.0
    │   │ │ ├── robust-orientation@1.1.3
    │   │ │ └─┬ slab-decomposition@1.0.2
    │   │ │   └── robust-orientation@1.1.3
    │   │ └── robust-orientation@1.1.3
    │   └─┬ simplify-planar-graph@2.0.1
    │     └── robust-orientation@1.1.3
    └── robust-orientation@1.1.3
    

    at:

    file: robust-orientation/orientation.js
    func: orientation
    line: var proc = new Function("sum", "prod", "scale", "sub", code)
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: surface-nets

    plotly.js@1.58.1
    ├─┬ gl-contour2d@1.1.7
    │ └── surface-nets@1.0.2
    ├─┬ gl-scatter3d@1.2.3
    │ └─┬ vectorize-text@3.2.1
    │   └── surface-nets@1.0.2
    └─┬ gl-surface3d@1.6.0
      └── surface-nets@1.0.2
    

    at:

    file: surface-nets/surfacenets.js
    func: buildSurfaceNets
    line: var proc = new Function("genContour", code.join(""))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d yes
    gl3d yes

    dependency: incremental-convex-hull

    plotly.js@1.58.1
    ├─┬ convex-hull@1.0.3
    │ └── incremental-convex-hull@1.0.1
    └─┬ delaunay-triangulate@1.1.6
      └── incremental-convex-hull@1.0.1
    

    at:

    file: incremental-convex-hull/ich.js
    func: bakeOrient
    line: var proc = new Function("test", code.join(""))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d no
    gl3d yes

    dependency: ndarray-sort

    plotly.js@1.58.1
    └─┬ gl-mesh3d@2.3.1
      └─┬ simplicial-complex-contour@1.0.2
        └── ndarray-sort@1.0.1
    

    at:

    file: ndarray-sort/lib/compile_sort.js
    func: createInsertionSort
    line: var result = new Function("malloc", "free", code.join("\n"))
    

    and

    at:

    file: ndarray-sort/lib/compile_sort.js
    func: createInsertionSort
    line: var result = new Function(code.join("\n"))
    

    and

    at:

    file: ndarray-sort/lib/compile_sort.js
    func: createQuickSort
    line: var compiled = new Function("insertionSort", "malloc", "free", code.join("\n"))
    

    and

    at:

    file: ndarray-sort/lib/compile_sort.js
    func: createQuickSort
    line: var new Function("insertionSort", code.join("\n"))
    

    and

    at:

    file: ndarray-sort/lib/compile_sort.js
    func: createQuickSort
    line: var result = new Function("insertionSort", "quickSort", code.join("\n"))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d no
    gl3d yes

    dependency: robust-determinant

    plotly.js@1.58.1
    └─┬ gl-mesh3d@2.3.1
      └─┬ barycentric@1.0.1
        └─┬ robust-linear-solve@1.0.0
          └── robust-determinant@1.1.0
    

    at:

    file: robust-determinant/robust-determinant.js
    func: compileDeterminant
    line: var proc = new Function("sum", "scale", "prod", "compress", [
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d no
    gl3d yes

    dependency: robust-linear-solve

    plotly.js@1.58.1
    ├─┬ alpha-shape@1.0.0
    │ └─┬ alpha-complex@1.0.0
    │   └─┬ circumradius@1.0.0
    │     └─┬ circumcenter@1.0.0
    │       └── robust-linear-solve@1.0.0
    └─┬ gl-mesh3d@2.3.1
      └─┬ barycentric@1.0.1
        └── robust-linear-solve@1.0.0
    

    at:

    file: robust-linear-solve/linsolve.js
    func: generateSolver
    line: var proc = new Function("det", code.join(""))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d no
    gl3d yes

    dependency: simplicial-complex-contour

    plotly.js@1.58.1
    └─┬ gl-mesh3d@2.3.1
      └── simplicial-complex-contour@1.0.2
    

    at:

    file: simplicial-complex-contour/lib/codegen.js
    func: createCellPolygonizer
    line: var proc = new Function('pool', code.join(''))
    
    bundle impacted
    basic no
    cartesian no
    finance no
    geo no
    mapbox no
    gl2d no
    gl3d yes

  21. tdelmas commented on Dec 21, 2020

    @tdelmas

    @archmoj Here is the list of GitHub repository involved in the list you provided, with, when available, the issue and/or the PR about CSP:

    As @mikolalysenko / @scijs doesn't seam to want to address the problem, most of the dependency you cited (probably around 50 packages?) may require to be forked...

  22. nicolaskruchten commented on Jan 5, 2021

    @nicolaskruchten
    Contributor

    It seems like a fair number of the items above that impact gl2d stem from gl-contour2d, so dropping support for the contourgl trace would resolve a number of these for the gl2d bundle, right?

  23. nicolaskruchten commented on Feb 18, 2021

    @nicolaskruchten
    Contributor

    An update: thanks to generous sponsorship from Equinor, we have been able to make substantial progress on this issue! I've just posted the pre-release announcement for Plotly.js 2.0, which will include the following changes related to this issue:

    1. The following official partial bundles no longer use function-constructors: basic, cartesian, finance, geo, and mapbox.
    2. A new partial bundle called strict will be supported from now on, and it contains the maximal subset of the library which is function-constructor-free (see link for list of trace types).
    3. Tests have been added to our CI such that the introduction of new usages of function-constructors will be considered a regression, meaning that we are committing to maintaining the status of the above bundles.
    4. As more sponsorship becomes available, we will continue to work on refactoring away the usage of function constructors in the various remaining gl2d and gl3d trace types (which involves upgrading various sub-dependencies, as listed in the comments above), such that the strict bundle will eventually grow to include the entire library, and such that we can eventually add the gl2d and gl3d partial bundles to the list of function-constructor-free bundles.
    5. We are developing a new and easier way for folks to bundle custom partial bundles, in case there is a need for a subset of the strict bundle that doesn't happen to match what's in basic, cartesian, finance, geo, or mapbox.
    6. We have documented the technique that can be used to load an official or custom partial bundle into a Dash app so that Dash developers can benefit from these new CSP-safe bundles.
  24. nschloe commented on Jun 16, 2021

    @nschloe

    Big thanks for releasing plotly-strict! This actually made it possible for me to use it in a browser extension for displaying plotly graphs in GitHub READMEs etc.:

    screenshot

    This wasn't possible before because browser extensions disallow eval()/function constructors.

  25. archmoj commented on Jul 30, 2021

    @archmoj
    Contributor

    The number of function constructors were slightly higher that those initially listed above.
    Namely Function.apply calls were not catch by eslint test.
    The list is now updated on #5869.

  26. archmoj commented on Sep 3, 2021

    @archmoj
    Contributor

    🎉 The v2.5.0 release removed calls to function constructor from various dependencies of gl3d traces as well as heatmapgl and pointcloud.

    It is now possible to apply CSP directives e.g.

    <meta http-equiv="Content-Security-Policy" content="script-src 'self'; worker-src blob:; ">
    to render & interact with those stackgl-based traces using "strict" or "gl3d" bundles.

  27. archmoj commented on Mar 15, 2022

    @archmoj
    Contributor

    Addressed by various PRs. Now one could use the strict bundles e.g. https://www.npmjs.com/package/plotly.js-strict-dist-min

  28. added a commit that references this issue on Aug 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    communitycommunity contribution

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions