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

fix(ses): makeError defaults to making passable errors #2200

Merged
merged 1 commit into from
Apr 6, 2024

Conversation

erights
Copy link
Contributor

@erights erights commented Apr 5, 2024

closes: #2198
refs: #2156

Description

The symptoms of #2156 reveal that some hosts add "extraneous" or harmful own properties to errors

  • Chrome, Brave (v8) adds an own stack accessor property, whose getter and setter functions can be used for mischief.
  • Firefox (SpiderMonkey) adds own fileName and lineNumber properties that are useful for diagnostics but should be redacted from public view.
  • Safari (JSC) adds an own line property, that likewise is useful for diagnostics, but should be redacted from public view.

Note that the contents of the stack should also be redacted from public view, but SES already deals with that separately.

Prior to this PR, some code assumed that the error that makeError returns would be passable once frozen. But these extra own properties, or own accessor properties, added by the host before makeError returns the error, caused it not to be passable, causing #2198 . As of this PR, makeError by default makes reasonable effort to return a passable error despite such host-added own properties. However, some code took advantage of the mutability of the error that makeError was returning, so this PR adds a sanitize: false option to suppress this cleaning and freezing of the returned error.

makeError does not guarantee that the returned error is passable, no matter what cause or errors options are provided. The purpose of this new sanitization behavior is to protect against host mischief. To test or coerce an error into a passable error, use toPassable in @endo/pass-style.

Security Considerations

Having makeError, by default, return errors that are already better behaved and more discreet helps security. However, because the underlying platform makes errors that are not sanitized in this manner, this PR doesn't help security significantly.

Scaling Considerations

none

Documentation Considerations

I added doc-comments to the makeError options doc-comment. However, the important added doccomment is on the new sanitizeError function which is encapsulated with SES's assert.js. I made a TODO that I don't know how one doccomment can link to another.

Testing Considerations

This problem was caught by accident. We should do enough browser-based testing early enough that problems like this would be caught first by purposeful testing.

Compatibility Considerations

This PR is staged on #2156. Like #2156, it presents a compat problem in theory but likely not in practice. #2156 stops exporting isPassableError and assertPassableError, which it turns out were never correct but which no one imports or uses.

This PR changes makeError to return a "sanitized" and frozen error, where it used to return a non-sanitized and non-frozen error. I looked through every call to makeError in endo and agoric-sdk, and found one site that made use of the non-frozen nature of that error. However, makeError is much older, so it is more plausible that there are other such uses outside these two repos. To accommodate that one known use case and mitigate problems at possible others, this PR adds a sanitize: false option to makeError to recover the old behavior. That one known site uses this option.

I leave it to my reviewers whether this PR as well as #2156 should be marked with a ! or not. In theory both should be. IMO, we should mark neither with !. Please let me know.

Upgrade Considerations

Since this bug manifested for #2156 on unmarshalling, i.e., unserializing use the @endo/marshal mechanisms, that bug raises the possibility of an upgrade hazard -- that an error saved to durable storage before an upgrade might cause another error on the attempt to read it from durable storage after the upgrade. This PR prevents that hazard.

  • Includes *BREAKING*: in the commit message with migration instructions for any breaking change.
  • Updates NEWS.md for user-facing changes.

@erights erights self-assigned this Apr 5, 2024
@erights erights changed the base branch from master to markm-make-error-freezes April 5, 2024 02:08
@erights
Copy link
Contributor Author

erights commented Apr 5, 2024

Following the repro instructions at #2198 , without this PR I get the bug it describes on the console output of Brave (v8), Firefox (SpiderMonkey) and Safari (JSC). With this PR, I get the following screenshots, showing that the desired error is now successfully reported

Brave:
image

Firefox
image

Safari
image

@erights erights changed the title Markm sanitize errors fix(ses): makeError defaults to making passable errors Apr 5, 2024
@erights erights force-pushed the markm-sanitize-errors branch 2 times, most recently from 056e4ab to c99f530 Compare April 5, 2024 02:48
@erights erights marked this pull request as ready for review April 5, 2024 03:05
Base automatically changed from markm-make-error-freezes to master April 5, 2024 20:54
@erights
Copy link
Contributor Author

erights commented Apr 5, 2024

Now testing CI for Agoric/agoric-sdk#9201 with force:integration label and #endo-branch: markm-sanitize-errors. We'll see how it goes.

@erights
Copy link
Contributor Author

erights commented Apr 5, 2024

Now testing CI for Agoric/agoric-sdk#9201 with force:integration label and #endo-branch: markm-sanitize-errors. We'll see how it goes.

That CI run successful. All green.

packages/ses/src/error/types.js Show resolved Hide resolved
* - `sanitizeError` will ensure that any expected properties already
* added by the host are data
* properties, converting accessor properties to data properties as needed,
* such as `stack` on v8 (Chrome, Brave, Edge?)
Copy link
Contributor

@mhofman mhofman Apr 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like stack own accessors are not modified by this helper, what am I missing?

Edit: never mind, I missed the second loop

erights added a commit that referenced this pull request Apr 22, 2024
closes: #2198 
refs: #2230 #2200
https://chromium-review.googlesource.com/c/v8/v8/+/4459251 #2229 #2231


## Description

Alternative to #2229 that just hacks `harden` to directly repair a
problematic error own stack accessor property, replacing it with a data
property.

### Security Considerations

Both before and after this PR, `passStyleOf` will reject errors with the
v8 problematic error own stack accessor property, preventing the
unsafety at stake here. However, this would mean that much existing code
that used to be correct will break when run on a v8 with this problem.

### Scaling Considerations

Avoids any extra overhead on platforms without this problem, including
all platforms other than v8.

### Documentation Considerations

probably none. This PR essentially avoids the need to document the v8
problem that it masks.

### Testing Considerations

Only needed to repair one test to use `harden` rather than `freeze`, in
a case where `harden` was more natural anyway.

### Compatibility Considerations

This PR enables more errors to pass that check without further changes
to user code. #2229 had similar goals, but would still require more
changes to user code than this PR. This is demonstrated by all the test
code in #2229 that needed to be fixed that does not need to be fixed in
this PR.

### Upgrade Considerations

none

- ~[ ] Includes `*BREAKING*:` in the commit message with migration
instructions for any breaking change.~
- ~[ ] Updates `NEWS.md` for user-facing changes.~
@erights erights mentioned this pull request May 6, 2024
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

Successfully merging this pull request may close these issues.

Marshal fails to rehydrate errors in Chrome, Firefox, Safari
3 participants