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

"Not allowed to load local resource" for "file://" URI -- but only on npm start, not after it is packaged #3098

Open
3 tasks done
cwellsx opened this issue Nov 27, 2022 · 5 comments

Comments

@cwellsx
Copy link

cwellsx commented Nov 27, 2022

Pre-flight checklist

  • I have read the contribution documentation for this project.
  • I agree to follow the code of conduct that this project uses.
  • I have searched the issue tracker for a bug that matches the one I want to file, without success.

Electron Forge version

6.0.3

Electron version

v21.2.2

Operating system

Windows 10

Last known working Electron Forge version

No response

Expected behavior

This should successfully display an image:

  • The renderer process tries to display an image using an <img src={url}/> element
  • The url is formatted using url.pathToFileURL(path).toString() e.g. file:///C:/Users/Christopher/Pictures/screenshot.png
  • The path is of an image file which exists on the local fie system, e.g. C:\Users\Christopher\Pictures\screenshot.png

The application is based on (i.e. built using) the Webpack Plugin template.

Actual behavior

This works OK, when the application.exe is launched from the local file system -- after it has been packaged using npm run package.

But it fails when it's run using npm start which loads the script from a web server (for hot reloading).

The error message in the console is,

  • Not allowed to load local resource: file:///C:/Users/Christopher/Pictures/screenshot.png

Steps to reproduce

Try an element like this in the renderer when you load it using npm start (but change the path to that of a file which exists on your machine).

  • <img src="file:///C:/Users/Christopher/Pictures/screenshot.png" />

Additional information

I guess that the error message ("Not allowed to load local resource") is coming from Electron not from the web server.

It's a common error message -- but different error causes -- on the Electron site:


I found I can write a hack as follows which bypasses this problem:

  • convertPathToUrl encodes any path as a URL using a non-standard local:// scheme instead of the file:// scheme
  • registerFileProtocol is called once on app start to implement support for this non-standard local:// scheme
import { protocol } from 'electron';
import url from 'node:url';

// use this to determine whether to hack behaviour because it's running from web server instead of from file system
const isRunningFromWebServer = __dirname.includes(".webpack");

// not defined in https://en.wikipedia.org/wiki/List_of_URI_schemes, used as a hack when running from web server
const schemeName = "local";
const scheme = `${schemeName}://`;

export const convertPathToUrl: (path: string) => string = (path: string) => {
  return !isRunningFromWebServer ? url.pathToFileURL(path).toString() : `${scheme}${encodeURIComponent(path)}`;
};

export function registerFileProtocol() {
  if (!isRunningFromWebServer) return;
  protocol.registerFileProtocol(schemeName, (request, callback) => {
    // undo the mangling that was done in convertPathToUrl
    const path = decodeURIComponent(request.url.slice(scheme.length));
    try {
      return callback(path);
    } catch (error) {
      console.error(`ERROR: registerFileProtocol: Could not get file path: error: ${error}, path: ${path}`);
    }
  });
}

When it's run this causes a different error message i.e.:

  • Refused to load the image '<URL>' because it violates the following Content Security Policy directive: "default-src 'self' 'unsafe-inline' data:". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

And that error message can be fixed by adding devContentSecurityPolicy to the WebpackPlugin in forge.config.ts to add support for the local: scheme to img-src:

  plugins: [
    new WebpackPlugin({
      devContentSecurityPolicy: `default-src 'self' 'unsafe-inline' data:; script-src 'self' 'unsafe-eval' 'unsafe-inline' data:; img-src local:`,
      mainConfig,
      renderer: {

So that's kind of OK: I can work with it.
But it's inconvenient for developers to discover this.
The reason I'm using Electron is to read files on the local file system, this was unexpectedly difficult.
So it would be nice if you could find a way to avoid this, in the default build-and-run.
It's bizarre that something (i.e. vanilla file:// URLs) should work in the released/packaged build but not in the debug/start build.

@cwellsx cwellsx changed the title "Not allowed to load local resource" for "file://" URI -- bu only on npm start, not after it is packaged "Not allowed to load local resource" for "file://" URI -- but only on npm start, not after it is packaged Nov 27, 2022
@MarshallOfSound
Copy link
Member

So that's kind of OK: I can work with it.
But it's inconvenient for developers to discover this.
The reason I'm using Electron is to read files on the local file system, this was unexpectedly difficult.

Agreed this is somewhat inconvenient but it's a documentation issue only as this is functionally working as expected. You shouldn't just be loading files ad-hoc from file:// as it's generically unsafe. Using a custom protocol and specifically allowed files is much Better ™️ anyway.

@cwellsx
Copy link
Author

cwellsx commented Nov 28, 2022

You shouldn't just be loading files ad-hoc from file:// as it's generically unsafe.

Isn't this, e.g. "loading files", like the main reason for using Electron at all instead of a web browser like Chrome?
I.e. to be a desktop application which CAN access local files?
For example I thought that, famously, VS Code is implemented with Electron: and IT sure can access local files.

And if were unsafe to use file:// then why I can do it in the packaged app but not during development?
IMO the restriction isn't by design, instead it's only a side-effect of using an embedded web server during development for hot reloading.

You say it's a documentation issue; does that mean you'll document it somewhere, or is it already documented somewhere?

@lazytyper
Copy link

file:// urls are not allowed when the files are loaded via http protocol.
This is the default case when you start the project with npm start.
You need to turn off hot reloading.

@mbrand2001
Copy link

You shouldn't just be loading files ad-hoc from file:// as it's generically unsafe.

Isn't this, e.g. "loading files", like the main reason for using Electron at all instead of a web browser like Chrome? I.e. to be a desktop application which CAN access local files? For example I thought that, famously, VS Code is implemented with Electron: and IT sure can access local files.

And if were unsafe to use file:// then why I can do it in the packaged app but not during development? IMO the restriction isn't by design, instead it's only a side-effect of using an embedded web server during development for hot reloading.

You say it's a documentation issue; does that mean you'll document it somewhere, or is it already documented somewhere?

Hi, I'm experiencing this issue as well, I'm able to get the loading to work through disabling webSecurity but I would prefer not to do that. I am still learning the ropes and I dont fully understand the "hacky" solution provided. Would someone be able to provide some guidance on how to navigate this issue? it would be greatly appreciated.

@Solitario119
Copy link

You shouldn't just be loading files ad-hoc from file:// as it's generically unsafe.

Isn't this, e.g. "loading files", like the main reason for using Electron at all instead of a web browser like Chrome? I.e. to be a desktop application which CAN access local files? For example I thought that, famously, VS Code is implemented with Electron: and IT sure can access local files.
And if were unsafe to use file:// then why I can do it in the packaged app but not during development? IMO the restriction isn't by design, instead it's only a side-effect of using an embedded web server during development for hot reloading.
You say it's a documentation issue; does that mean you'll document it somewhere, or is it already documented somewhere?

Hi, I'm experiencing this issue as well, I'm able to get the loading to work through disabling webSecurity but I would prefer not to do that. I am still learning the ropes and I dont fully understand the "hacky" solution provided. Would someone be able to provide some guidance on how to navigate this issue? it would be greatly appreciated.

I have the same question too. Have you found a solution yet? It would be greatly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants