This line makes Dexie not really CSP (Content Security Policy) compliant because it needs adding 'unsafe-eval' within script-src, wich is not a good practice ! Could it be remplaced in order to correct this issue (Function(str) is eval) ? Thank you
The code above tries to detect if async functions are supported.
I am not an expert on this topic, but I don't understand why we need to differentiate between async functions and promises, at all.
Example:
const myAsync = async () => 'foo'
is basically the same as:
const myAsync = () => Promise.resolve('foo')
So we are testing/optimizing an implementation detail of js, that should be not part of this project.
So my recommendation is to handle async functions in the same way we handle Promises.
@dfahlander Please let me know, if I am on the wrong track here. đź¤
@SlIdE42 if you are using webpack, you can use string-replace-loader to patch dexie.js on the fly.
Example:
module.exports = {
// ...
module: {
rules: [
{
test: /dexie[\\/]+dist[\\/].*\.js$/,
loader: 'string-replace-loader',
options: {
search: 'return new Function(`let F=async ()=>{},p=F();return [p,Object.getPrototypeOf(p),Promise.resolve(),F.constructor];`)();',
replace: 'return [Promise.resolve(), Promise.prototype, Promise.resolve(), Function.constructor]',
}
}
]
}
}
Nevertheless thanks for this awesome project. It has been a charm using it ♥.
@HaNdTriX We basically have to distinguish the built-in promise from a polyfilled one. There are two reasons that Dexie deals with this low-level stuff. First, because IndexedDB Transactions does not work with native Promises on all browsers, so Dexie bridges that incompatibility using its own promise implementation. Two years back, this was the case for all browsers except Chrome. Nowadays, it only applies to older browsers, as Firefox recently solved the issue in its very latest version. The second reason is that Dexie's API depends on a zone system that works across native async calls and we need to detect that as polyfilled Promise would give other results than an async result. We don't want the code to be transpiled, that's why it is written in a string.
So basically, native async calls will not work as expected without this code. As long as you transpile away your "async" and "await" app code, your patch will work fine.
Could fix this withing Dexie's build system instead though (by omitting transpilation of specific parts of the code). EDIT: Not possible as older browsers would discard the entire JS file if it contained async keyword.
@SlIdE42 You can apply @HaNdTriX patch if you target older browsers and transpile all your code to ES5 or ES6, or keep away from async/await, or make sure to not have any promise polyfill.
I ran into this while trying to use Dexie.js in a browser add-on (webextensions). On Firefox I get this error:
Content Security Policy: The page’s settings blocked the loading of a resource at eval (“script-src”). dexie.js:630:15
Which appears to be the same line at the top of this issue:
return new Function("let F=async ()=>{},p=F();return [p,Object.getPrototypeOf(p),Promise.resolve(),F.constructor];")();
There is a way to prevent the error by not using the default CSP, but that might cause the add-on to be rejected. As described on MDN's best security practices:
Use the standard extension content security policy (CSP)
The standard policy [...] disallows potentially unsafe practices such as the use of eval(). While the manifest.json key content_security_policy enables you to modify the content security policy for your extension, this isn’t recommended as the policy helps prevent extensions from inadvertently executing malicious content. If your modified CSP allows remote script injection your extension will get rejected from AMO during review.
For this use case (browser add-on) I don't need to support older browsers. I'll try the non-default CSP, option and if that doesn't work, I'll look into using the 'patch dexie' work-around shown above, but wanted to mention this as another use case where this comes up.
And... modifying 3rd party libraries is also a red flag, per MDN's security best practices:
Do not modify third-party libraries
Modifications to a third-party library are a significant indicator that a developer is trying to hide malicious code within code that is generally known and trusted. AMO will therefore try to detect changes to third-party libraries and may disable extensions when it finds changes.
@dfahlander This CSP-offending code does not seem to exist in Dexie v3, how did you solve it there?
@dfahlander This CSP-offending code does not seem to exist in Dexie v3, how did you solve it there?
Still seems to be there as far as I can tell:
https://github.com/dfahlander/Dexie.js/blob/master/src/helpers/promise.js#L47
@dfahlander This CSP-offending code does not seem to exist in Dexie v3, how did you solve it there?
Still seems to be there as far as I can tell:
https://github.com/dfahlander/Dexie.js/blob/master/src/helpers/promise.js#L47
@birtles You're right, I thought v3 was being tracked in the next/v3 branch. As you pointed out, it's being tracked in master, and unfortunately the offending code still seems to be required.
I found a solution to distinguish polyfilled promise from the native one without breaking the CSP. Will be included in next version (will be 3.0.0-beta.1). Planning to release a stable 3.0.0 within a week or two.
Thanks so much @dfahlander! Is there an updated estimate on the release date of the stable 3.0.0?
I'll see what possibility there is to release it this week. But not later than mid November.
Most helpful comment
I found a solution to distinguish polyfilled promise from the native one without breaking the CSP. Will be included in next version (will be 3.0.0-beta.1). Planning to release a stable 3.0.0 within a week or two.