flutterfire
flutterfire copied to clipboard
🐛 [firebase_core_web] TrustedType violations in firebase_core_web.dart - TrustedScript needed
Bug report
Several Google Flutter web apps using Firebase plugins that rely on firebase_core_web are receiving browser error reports through the TrustedTypes browser APIs. Specifically, the script injection code in _injectSrcScript is not adhering to the standards and is causing errors to be logged.
We really want to get this fixed so that we can enable new security features which will protect our apps from certain types of vulnerability.
This was previously reported in https://github.com/firebase/flutterfire/issues/10311 and a fix attempted in https://github.com/firebase/flutterfire/pull/10312, however the fix didn't work (see below). It would be amazing if you could try to reproduce the issue with steps below and verify that using a TrustedScript fixes it.
Currently, we have code like:
web.TrustedScriptURL? trustedUrl;
final trustedTypePolicyName = _defaultTrustedPolicyName + windowVar;
if (web.window.nullableTrustedTypes != null) {
web.console.debug(
'TrustedTypes available. Creating policy: $trustedTypePolicyName'.toJS,
);
try {
final web.TrustedTypePolicy policy =
web.window.trustedTypes.createPolicy(
trustedTypePolicyName,
web.TrustedTypePolicyOptions(
createScriptURL: ((JSString url) => src).toJS,
),
);
trustedUrl = policy.createScriptURLNoArgs(src);
} catch (e) {
throw TrustedTypesException(e.toString());
}
}
final web.HTMLScriptElement script =
web.document.createElement('script') as web.HTMLScriptElement;
script.type = 'text/javascript';
script.crossOrigin = 'anonymous';
final stringUrl = trustedUrl != null
// Necessary for the JS interop to work correctly on Flutter Beta 3.19.
// ignore: unnecessary_cast
? (trustedUrl as JSObject).callMethod('toString'.toJS)
: src;
script.text = '''
window.ff_trigger_$windowVar = async (callback) => {
console.debug("Initializing Firebase $windowVar");
callback(await import("$stringUrl"));
};
''';
The issue here is that although we do create a trusted types policy to create a TrustedScriptURL (added in the previous fix), we're still "unsafely" setting the text of the Script element (e.g. dynamically creating an inline script) rather than its URL. So even though we embed the DomTrustedScriptUrl in the inline script, overall the entire inner javascript is untrusted. It seems like we should actually use a TrustedScript policy here to create a trusted script to embed - see https://developer.mozilla.org/en-US/docs/Web/API/TrustedScript.
Also see related issue https://github.com/firebase/firebase-js-sdk/issues/7048 which was fixed.
Steps to reproduce the behavior:
-
Create an example Flutter web app using Firebase
-
Enable trusted types enforcement, e.g. by adding:
<meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script'" /> -
Load page, and look for errors in the JS console
Expected behavior
Setting the text on the script tag should not produce a trusted types error.
I was able to replicate it by adding the said meta tag which resulted in below:
Removing the tag built the app properly without any errors.
I used firebase_core plugin example.
Thanks so much for replicating, @darshankawar ! I hope with TrustedScript, we can assign that script src in way that supports trusted types. I'm still not certain whether we also need to use the TrustedScriptURL that is already present, but perhaps you can test that part out.
Thank you for the quick fix on this!! We'll roll this into Google and give it a try!