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

Security warning: avoid using function constructor. #897

Closed
feugy opened this issue Sep 2, 2016 · 34 comments
Closed

Security warning: avoid using function constructor. #897

feugy opened this issue Sep 2, 2016 · 34 comments
Labels
♥ NEEDS SPON$OR Help bring this feature to LTS status type: community

Comments

@feugy
Copy link

feugy commented Sep 2, 2016

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 ?

@rreusser
Copy link
Contributor

rreusser commented Sep 2, 2016

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.

@etpinard
Copy link
Contributor

etpinard commented Sep 2, 2016

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).

@willemx
Copy link

willemx commented Apr 12, 2017

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

@jacobq
Copy link

jacobq commented Feb 27, 2018

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

@fxfilmxf
Copy link

fxfilmxf commented Mar 9, 2018

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

@etpinard
Copy link
Contributor

etpinard commented Mar 9, 2018

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.

@fxfilmxf
Copy link

fxfilmxf commented Mar 9, 2018

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

@jtal
Copy link

jtal commented Nov 6, 2018

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

@jacobq
Copy link

jacobq commented Nov 7, 2018

@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

@anders-kiaer
Copy link

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).

@etpinard
Copy link
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.

@anders-kiaer
Copy link

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.

@etpinard
Copy link
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.

@etpinard
Copy link
Contributor

etpinard commented Feb 12, 2020

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.

@alexcjohnson
Copy link
Collaborator

FWIW I don't think it would be unreasonable to explore making an eval-free version of cwise - it's not the eval that gives it its speed, it's just using that to do codegen and reduce its own size. But at the end of the day I'd expect gzip means this codegen isn't even saving that many bytes over the wire... not a guarantee, but if someone wants to explore that we would certainly entertain it.

tdelmas added a commit to tdelmas/website that referenced this issue Feb 16, 2020
tdelmas added a commit to tdelmas/website that referenced this issue Feb 16, 2020
From v1.48.3 to v1.52.2 and downgrade from full to basic (to avoid plotly/plotly.js#897)
@tdelmas
Copy link
Contributor

tdelmas commented Feb 16, 2020

The current version 1.52.2 (https://raw.githubusercontent.com/plotly/plotly.js/v1.52.2/dist/plotly.js) uses Fonction in eval mode in those places:

tdelmas added a commit to letsencrypt/website that referenced this issue Feb 23, 2020
* Update plotly-min.js

From v1.48.3 to v1.52.2 and downgrade from full to basic (to avoid plotly/plotly.js#897)

* Add "img-src blob:" is for Plotly download feature and comments
@archmoj
Copy link
Contributor

archmoj commented Jun 23, 2020

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?

@anders-kiaer this is done in #4929 and #4930 and available in plotly.js >= v1.54.4

@archmoj
Copy link
Contributor

archmoj commented Sep 3, 2021

🎉 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.

@archmoj
Copy link
Contributor

archmoj commented Mar 15, 2022

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
♥ NEEDS SPON$OR Help bring this feature to LTS status type: community
Projects
None yet
Development

No branches or pull requests