webview and local iframes (Access-Control-Allow-Origin)
dbadb opened this issue · 7 comments
I have a situation where my local "website" wants to load local "sub-websites" into their own iframe.
Mostly this works but if the external "website" loads a font-file via its private css, we get interesting CORS errors like these
Access to font at 'choc://choc.choc/C:/path/to/subwebsite/fonts/Wierd.ttf' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I found that adding "Access-Control-Allow-Origin: *" to the resource-served headers (cf near line 1321 of choc_WebView.h)
resolves the issue. This probably doesn't introduce any more security concerns than those represented by any WebView app running with full privileges on a user's computer.
Happy to submit a PR on request.
cheers
The fix you're suggesting would be just to the Windows code - have you tried it on other platforms?
Add the header would clearly work, but I wonder if it still works with restricted access to only the internal resource domain, e.g. Access-Control-Allow-Origin: choc://choc.choc
?
I have yet to try the other platforms though I made the same simple change in 3 places in my branch.
For more context, the behavior I'm after is for safe sandboxing as described here.
When creating a safe iframe sandbox, the iframe origin is explicitly != the parent origin
so this is why explicitly setting ACAO to eg choc://choc.choc doesn't work. This is the implicit default behavior.
One can create a sandboxed iframe with "allow-same-origin" and probably achieve a similar result. The problem with this is that it grants access to iframe javascript to other aspects of the parent environment (localStorage and even the entire parent DOM).
The approach outlined here is to allow the "server" to serve any file it likes constraining access by datatypes or URL by returning 404 when it detects the null origin.
For what it's worth, I've just had a similar problem trying to load a resource from JavaScript using fetch()
. The following change works for me on macOS:
diff --git a/gui/choc_WebView.h b/gui/choc_WebView.h
index 25983ef..8dd5f92 100644
--- a/gui/choc_WebView.h
+++ b/gui/choc_WebView.h
@@ -478,8 +478,8 @@ private:
const auto& [bytes, mimeType] = *resource;
auto contentLength = std::to_string (bytes.size());
- id headerKeys[] = { getNSString ("Content-Length"), getNSString ("Content-Type"), getNSString ("Cache-Control") };
- id headerObjects[] = { getNSString (contentLength), getNSString (mimeType), getNSString ("no-store") };
+ id headerKeys[] = { getNSString ("Content-Length"), getNSString ("Content-Type"), getNSString ("Cache-Control"), getNSString ("Access-Control-Allow-Origin") };
+ id headerObjects[] = { getNSString (contentLength), getNSString (mimeType), getNSString ("no-store") , getNSString ("*") };
id headerFields = call<id> (getClass ("NSDictionary"), "dictionaryWithObjects:forKeys:count:",
headerObjects, headerKeys, sizeof (headerObjects) / sizeof (id));
Using choc://choc.choc
instead of *
also solves my problem.
@jdv85 just for completeness can you describe what your fetch url and origin looks like?
- does the fetch url include a uri_scheme or is it just a www-relative path (choc://choc.choc/path-to-resource or /path-to-resource)?
- is your fetch invoked from within an iframe context or is this just a standard fetch request?
- does the fetch url include a uri_scheme or is it just a www-relative path (choc://choc.choc/path-to-resource or /path-to-resource)?
Both work for me.
- is your fetch invoked from within an iframe context or is this just a standard fetch request?
I'm not using iframe
, sorry for not being clear about that in the first place.
Thanks - this does seem pretty simple, I've pushed some changes to develop. Let me know if you have any problems with them.
just did the integrate and can confirm functionality on win32 and apple platform so far.