electron: contextBridge.exposeInMainWorld does not copy Error details

Preflight Checklist

  • I have read the Contributing Guidelines for this project.
  • I agree to follow the Code of Conduct that this project adheres to.
  • I have searched the issue tracker for an issue that matches the one I want to file, without success.

Issue Details

When calling functions exposed by contextBridge.exposeInMainWorld, Promises rejected with Error objects or directly thrown Errors (and even caught Errors returned in a wrapper) are not copied as the documentation states – all important information except the message is removed, e.g. Common System Error properties like err.code, err.path etc. are gone. Also, the “Uncaught Error: ” message prefix is not very helpful.

  • Electron Version:
    • 10.1.2
  • Operating System:
    • Windows 10 (2004)

Expected Behavior

Instances of the Error class (or inherited from it) coming from the context bridge should have all properties preserved (except err.stack, obviously) and message left intact to allow meaningful error handling. Structured Clone Algorithm otherwise serializes Error objects correctly.

Actual Behavior

The Error object is stripped of important additional properties and has a confusing message saying it’s uncaught even when caught on both sides of the bridge.

To Reproduce

preload.js

const { contextBridge } = require('electron');
const fs = require('fs');

contextBridge.exposeInMainWorld('myapi', {
  request: () => fs.lstatSync('foo')
});

renderer

try {
  window.myapi.request();
} catch (e) {
  console.dir(e);
}

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 11
  • Comments: 17 (11 by maintainers)

Most upvoted comments

Thanks for having a look at it. In my case, knowing why a request failed is needed - the app works with files, folders and lockfiles often located on shared network drives etc. where permission and accessibility errors occur – the app will retry or inform the user based on the error details. I understand the security concerns, it’d just be nice if I didn’t have to restructure the code to return the error details inside a plain object and could just catch an exception instead. An option for exposeInMainWorld to allow Errors to pass would be handy.

Bump

@richardfritsch We follow the same strategy for cross-boundarysanitization as chrome. If you try and dispatchEvent with a custom Event object with custom properties those properties will be lost when accessing that event in another world. Errors are tricky because we as a framework don’t know what could be in the custom properties on Error objects and don’t want to let users shoot themselves in the foot by setting custom properties on error objects that then get leaked into the main world.

IMO in your case of fs usage the renderer should never know why the request failed, just that for some reason it did. Passing details like error code and in particular the filesystem path is counter to the goals of isolated the untrusted renderer from that kind of information.