aframevr / aframe

:a: Web framework for building virtual reality experiences.
https://aframe.io/
MIT License
16.68k stars 3.98k forks source link

Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script #5028

Open samiemad opened 2 years ago

samiemad commented 2 years ago

Description: When loading the library, the browser throws 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: "script-src 'self' [...]"

Looking into the stack trace, I see these lines from https://github.com/aframevr/aframe/blob/master/dist/aframe-master.js

//getters for the private vars
;['width', 'height', 
  'descender', 'ascender',
  'xHeight', 'baseline',
  'capHeight',
  'lineHeight' ].forEach(addGetter)

function addGetter(name) {
  Object.defineProperty(TextLayout.prototype, name, {
    get: wrapper(name),
    configurable: true
  })
}

//create lookups for private vars
function wrapper(name) {
  return (new Function([
    'return function '+name+'() {',
    '  return this._'+name,
    '}'
  ].join('\n')))()
}

Looks like aframe requires unsafe-eval to be allowed which is quite dangerous. Is there a workaround to use aframe without enabling unsafe-eval??

Can this be replaced by something safer? like:

    get: function () {
      return this['_'+name]
    },

Thanks!

dmarcos commented 2 years ago

Can you provide a link to an example to reproduce?

An example loading the library just fine: https://glitch.com/~aframe

samiemad commented 2 years ago

Yes sure. Adding the content security policy breaks it.

Here is the code to reproduce: https://glitch.com/edit/#!/few-coherent-guilty?previewSize=0&attributionHidden=false&sidebarCollapsed=false&path=&previewFirst=false

<!DOCTYPE html>
<html>
  <head>
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self';
      script-src 'self' https://aframe.io;
      style-src 'self' 'unsafe-inline';"
    />
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
  </head>
  <body>
    <a-scene>
      <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
      <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
      <a-cylinder
        position="1 0.75 -3"
        radius="0.5"
        height="1.5"
        color="#FFC65D"
      ></a-cylinder>
      <a-plane
        position="0 0 -4"
        rotation="-90 0 0"
        width="4"
        height="4"
        color="#7BC8A4"
      ></a-plane>
      <a-sky color="#ECECEC"></a-sky>
    </a-scene>
  </body>
</html>

After adding unsafe-eval to script-src 'self' https://aframe.io;, the page loads without problems

dmarcos commented 2 years ago

Do you need that meta tag? FWIW the unsafe-eval code you pointed comes from a dependency bet seems safe. Just adding getters automatically to the object.

samiemad commented 2 years ago

Yes, I agree it seems safe. But this setting is global. So if we allow it, it will be allowed for the whole web app and makes the whole app security lower. After all it's called unsafe for a reason.

OTOH, since it's a simple use-case of adding getters, it should not be too hard to replace with something safer, right?

Anyway, if you help me track that dependency I would be happy to try to fix the issue and create a PR.

dmarcos commented 2 years ago

Code is in https://github.com/Jam3/layout-bmfont-text/blob/master/index.js#L221

used by https://github.com/Jam3/three-bmfont-text

dmarcos commented 2 years ago

The quickest option is probably make and serve your own A-Frame build with the code corrected / removed.

samiemad commented 2 years ago

Thanks. I'll have a look and see what I can do.

andrevenancio commented 2 years ago

Hey @mattdesl Its been a while but has anyone updated this dependency on Jam3 side? Some providers just block content if there is an eval on the code.

Cloudflare does it, and causes issues loading on web3 platforms.

Here's an example with NFTStorage IPFS Gateway: https://bafybeidg3y34lewgcbarxgq4sayiwnl2lpb4smvxsic7cmzthv2rlov6de.ipfs.nftstorage.link/

And the same example with IPFS.IO Gateway: https://ipfs.io/ipfs/QmVGCppbY5cQ7XUqNzUS51uV4usS51UEzEQzpQ3ZLXh3NG/

The NFTStorage one uses cloudflare, and they do not allow evals as they allow for malicious code to be injected on the client.

vincentfretin commented 1 year ago

Someone on slack had the same error trying to embed aframe into a chrome extension where unsafe-eval is forbidden. If the issue is in the layout-bmfont-text dependency you can probably create your own aframe build without the text component by commenting the line require('./text'); in src/components/index.js (I have not tested it) and use some other component like https://github.com/lojjic/aframe-troika-text if you need to show some text.