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

[V6] unsafe-eval #3749

Closed
ohrrkan opened this issue Feb 8, 2023 · 13 comments
Closed

[V6] unsafe-eval #3749

ohrrkan opened this issue Feb 8, 2023 · 13 comments
Assignees
Labels
enhancement New feature or improvement. fixed/complete This Bug is fixed or Enhancement is complete and published. minor-bump Planned for the next minor version bump. v6 Issues regarding v6

Comments

@ohrrkan
Copy link

ohrrkan commented Feb 8, 2023

Ethers Version

6.0.2

Search Terms

unsafe-eval

Describe the Problem

We have a Strict CSP policy for security reason on our website. this mean eval is not allow.

Updating from v5 to V6 without change our CSP seem impossible as browser throw an error. do you confirm?

Code Snippet

No response

Contract ABI

No response

Errors

'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'

Environment

Ethereum (mainnet/ropsten/rinkeby/goerli)

Environment (Other)

No response

@ohrrkan ohrrkan added the investigate Under investigation and may be a bug. label Feb 8, 2023
@ohrrkan ohrrkan changed the title [V6] [V6] unsafe-eval Feb 8, 2023
@ricmoo
Copy link
Member

ricmoo commented Feb 8, 2023

There should definitely not be any eval used in ethers v6. Can you identify the source??

@ohrrkan
Copy link
Author

ohrrkan commented Feb 8, 2023

Going deeper, the specification list other similar methods that can trigger the error :

https://www.w3.org/TR/CSP3/#directive-script-src

The following JavaScript execution sinks are gated on the "unsafe-eval" source expression:

eval()
Function()
setTimeout() with an initial argument which is not callable.
setInterval() with an initial argument which is not callable.

NOTE: If a user agent implements non-standard sinks like setImmediate() or execScript(), they SHOULD also be gated on "unsafe-eval". Note: Since "unsafe-eval" acts as a global page flag, script-src-attr and script-src-elem are not used when performing this check, instead script-src (or it’s fallback directive) is always used.

I will investigate more.

@ricmoo
Copy link
Member

ricmoo commented Feb 9, 2023

In that case, maybe this is the problem?

https://github.com/ethers-io/ethers.js/blob/main/src.ts/providers/abstract-provider.ts#L1068

If so, it’s easy for me to wrap it in a () => (func()).

@ohrrkan
Copy link
Author

ohrrkan commented Feb 9, 2023

Seems the error is trigger by a conflict with somethings else => I cannot reproduce it in a vanilla environement for testing. Closing this issue for now and will re-open if I found the conflicting source.

@ohrrkan ohrrkan closed this as completed Feb 9, 2023
@ohrrkan
Copy link
Author

ohrrkan commented Feb 23, 2023

Re-open with more info :

Throw by

simple vanilla to reproduce index.html :

<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'" />
    <title>Test Page</title>
  </head>

  <body>
    <h1>Test Page</h1>
    <p id="content"></p>
    <script type="module" src="./index.js"></script>
  </body>
</html>

index.js

import { BrowserProvider, getDefaultProvider } from "./node_modules/ethers/dist/ethers.js";

async function main() {
  let provider;
  if (window.ethereum == null) {
    console.log("MetaMask not installed; using read-only defaults");
    provider = getDefaultProvider();
  } else {
    provider = new BrowserProvider(window.ethereum);
  }
  const balance = await provider.getBalance("ethers.eth");
  document.getElementById("content").innerHTML = balance;
}

main();

@ohrrkan ohrrkan reopened this Feb 23, 2023
@ricmoo
Copy link
Member

ricmoo commented Feb 23, 2023

I don’t understand why that would cause an eval issue? The function that is extends returns the Function class, which should have a super? Or you aren’t allowed to use Function sub-classes?

Do you have any more info on this warning?

@ohrrkan
Copy link
Author

ohrrkan commented Feb 23, 2023

the Full error log :

Uncaught (in promise) 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: "default-src 'self'".

    at new Function (<anonymous>)
    at new WrappedMethod (contract.js:168:9)
    at Contract.getFunction (contract.js:619:17)
    at Object.get (contract.js:560:39)
    at #getResolver (ens-resolver.js:420:41)
    at async EnsResolver.fromName (ens-resolver.js:451:26)
    at async BrowserProvider.getResolver (abstract-provider.js:700:16)
    at async BrowserProvider.resolveName (abstract-provider.js:710:26)
    at async checkAddress (checks.js:54:20)
    at async Promise.all (:3000/index 0)

@raulrpearson
Copy link

I'm getting something similar on Cloudflare Workers. It seems to appear when I call a contract's method. I created a repo with the reproduction in case it's helpful or maybe you can point out if I'm making some mistake. I haven't deployed, the error is triggered on npm run dev.

code-from-strings-disallowed

@EdenCrow
Copy link

EdenCrow commented Mar 6, 2023

I'm also getting this error when using ethers.js for a Chrome Extension. Manifest V3 seems to have stricter CSPs and won't allow my extension to run, while Manifest V2 does.

Uncaught (in promise) 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' 'wasm-unsafe-eval' 'inline-speculation-rules' http://localhost:* http://127.0.0.1:*".

    at new Function (<anonymous>)
    at new WrappedMethod (main.bundle.js:7452:9)
    at Contract.getFunction (main.bundle.js:7903:17)
    at Object.get (main.bundle.js:7844:39)
    at #getResolver (main.bundle.js:13676:41)
    at async EnsResolver.fromName (main.bundle.js:13707:26)
    at async EtherscanProvider.getResolver (main.bundle.js:15364:16)
    at async EtherscanProvider.resolveName (main.bundle.js:15374:26)
    at async getInfo (main.bundle.js:16430:24)

Seems to be the same place the error is thrown as mentioned before:

@ricmoo
Copy link
Member

ricmoo commented Mar 7, 2023

Linking this to #3763, which seems to have the same root cause.

@ricmoo ricmoo added on-deck This Enhancement or Bug is currently being worked on. v6 Issues regarding v6 labels Mar 7, 2023
@ricmoo
Copy link
Member

ricmoo commented Mar 9, 2023

Pretty sure I’ve figured out the problem, and have a solution. I’ll try it out and will release a minor bump (6.2.0) to address it.

@ricmoo ricmoo added enhancement New feature or improvement. minor-bump Planned for the next minor version bump. and removed investigate Under investigation and may be a bug. labels Mar 9, 2023
@ricmoo
Copy link
Member

ricmoo commented Mar 20, 2023

This has been addressed in v6.2.0. Please try it out and let me know if there are any problems. :)

@ohrrkan
Copy link
Author

ohrrkan commented Mar 21, 2023

Test ok. confirm it work for me. Thanks

@ohrrkan ohrrkan closed this as completed Mar 21, 2023
@ricmoo ricmoo added fixed/complete This Bug is fixed or Enhancement is complete and published. and removed on-deck This Enhancement or Bug is currently being worked on. labels Jun 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement. fixed/complete This Bug is fixed or Enhancement is complete and published. minor-bump Planned for the next minor version bump. v6 Issues regarding v6
Projects
None yet
Development

No branches or pull requests

4 participants