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

feat: add evalTaming option #961

Merged
merged 19 commits into from Feb 22, 2022
Merged

feat: add evalTaming option #961

merged 19 commits into from Feb 22, 2022

Conversation

Jack-Works
Copy link
Contributor

@Jack-Works Jack-Works commented Dec 18, 2021

This PR adds a new option evalTaming which defaults to "safeEval" (current behavior).

I introduced a new behavior "unsafeEval" and "noEval".

This option is for the environment that does not allow eval in the production mode but allows it in the development mode for webpack eval-source-map.
The current behavior will replace the eval constructor and cause the webpack bundle to fail to load.

I have documented this new option and warned any users do not use it unless they have the same situation as us.

Copy link
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

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

Hi @Jack-Works , very nice! Some questions:

IIUC, what you really care about is the Function and eval of the start compartment. Under the 'unsafe' setting you want these left as is. But I don't understand what you intend for the evaluate method of compartments, nor for the per-non-start-compartment setting of eval and Function.

For production use, IIUC, you want this to actually be safe if in an environment where evaluation is suppressed by other means, like CSP. However, in that environment specifically, how would it make a difference whether eval and Function were tamed or not? In fact, to better support that environment, should this PR instead have a three-settings option, perhaps with names like the following?

  • 'noEval' -- all evaluators are disabled, achieving no-eval safety with or without CSP. This would be compat with the CSP no-eval option, but would be redundant belt and suspenders, in case the CSP was, for example, mistakenly changed under maintenance.
  • 'safeEval' -- status quo
  • 'unsafeEval' -- supports the development mode you're concerned about, by leaving (only?) the start compartment eval and Function untamed.

I'm hitting "Request changes" but I'm really requesting dialog ;). I'd like your reaction to these questions before completing the review. Thanks!

@Jack-Works
Copy link
Contributor Author

'noEval' -- all evaluators are disabled, achieving no-eval safety with or without CSP. This would be compat with the CSP no-eval option, but would be redundant belt and suspenders, in case the CSP was, for example, mistakenly changed under maintenance.

What should happen for eval within a compartment? The compartment itself internally based on the real eval and provide a CSP-safe eval?

@Jack-Works
Copy link
Contributor Author

And is it possible to have different eval behavior in the start compartment and the child compartment? For example, start compartment has noEval and the child one has safeEval? Or start compartment with unsafeEval but child has noEval

@erights erights self-requested a review December 20, 2021 08:01
@erights
Copy link
Contributor

erights commented Dec 20, 2021

'noEval' -- all evaluators are disabled, achieving no-eval safety with or without CSP. This would be compat with the CSP no-eval option, but would be redundant belt and suspenders, in case the CSP was, for example, mistakenly changed under maintenance.

What should happen for eval within a compartment? The compartment itself internally based on the real eval and provide a CSP-safe eval?

Are you asking about the 'noEval' option specifically? In that case, all evaluators should be inert (only throwing errors), including those within compartments.

@erights
Copy link
Contributor

erights commented Dec 20, 2021

And is it possible to have different eval behavior in the start compartment and the child compartment? For example, start compartment has noEval and the child one has safeEval? Or start compartment with unsafeEval but child has noEval

It could be possible by other means. But I don't think appropriate for such lockdown options, since these are not per-compartment. I don't think we need to go that far in this PR.

@kriskowal
Copy link
Member

kriskowal commented Dec 20, 2021

I can only think of motivating uses to rationalize two modes: one where eval cannot be used in any form and one where we use eval. Which of these three modes do we not need and can we frame the remaining two in a way that makes the choice clearest to the end user?

Or: what’s the third motivating use case?

@Jack-Works
Copy link
Contributor Author

Updated cc @erights @kriskowal

@Jack-Works
Copy link
Contributor Author

ping @erights @kriskowal can u check out this PR?

@kriskowal
Copy link
Member

I’ve given this a scan and it looks close. I will ask @erights and @mhofman to sign off on the architecture and I will send a review with suggestions to clarify the feature documentation, which will help me think through the rationale for each of the taming options. This will need a short entry in NEWS

Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

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

This is good and close to merge-worthy, pending architecture approval from some combination of @erights and @mhofman. The code does not yet have the intended effect for the "unsafe" option.

I would like to propose the names "safe", "unsafe", and "none" for which there is precedent on other taming options.

I would like to see a test case that verifies that compartment evaluators work with the "unsafe" option.

Copy link
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

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

Environment variable misnamed?

Copy link
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

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

LGTM modulo lint errors.

Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

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

Now that I’ve slept on it, I agree with Mark that the taming option names should be noEval, safeEval, and unsafeEval. Mostly, none is not a good name. My apologies for making more work for you.

@Jack-Works Jack-Works requested a review from kriskowal January 28, 2022 16:48
Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

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

Thank you. This is looking great. I would like compartment evaluator tests for each of the modes.

It would also be good to test compartments constructed within another compartment, specifically to highlight the TODO you added regarding the propagation of evalTaming to child compartments. I expect safeEval will work fine, but noEval might not be working correctly.

Otherwise, nits.

Thank you for the drive-by cleanups.

@Jack-Works
Copy link
Contributor Author

hi @kriskowal can I get a review? this is blocking our product to adopt lockdown

@kriskowal kriskowal self-requested a review February 16, 2022 16:03
Copy link
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

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

It would be nice to add an error code doc. If you don’t, I’ll do that in follow-up. I would like to get @erights’s final stamp.

@kriskowal kriskowal dismissed their stale review February 16, 2022 16:09

I am satisfied and defer to @erights for final sign-off.

@Jack-Works
Copy link
Contributor Author

hi is this change you're expecting? I just pushed a new commit @kriskowal

@kriskowal
Copy link
Member

kriskowal commented Feb 16, 2022 via email

@Jack-Works Jack-Works requested a review from erights February 17, 2022 03:27
@kriskowal kriskowal requested a review from mhofman February 17, 2022 04:21
Copy link
Contributor

@mhofman mhofman left a comment

Choose a reason for hiding this comment

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

There is regression about marking the eval and Function globals as native functions.

I'm a little confused about the goal of noEval and the interaction with the Compartment shim. compartment.evaluate() is also an evaluator. Shouldn't it throw as well in the case of noEval taming? That would limit the usefulness of Compartment since the shim doesn't natively support ES modules (to replicate CSP, I would imagine only some modules would be allowed to be imported based on some policy)

Copy link
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

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

LGTM. All my comments are only on documentation.

Thanks for this enhancement!

Copy link
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

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

LGTM


```js
const c = new Compartment()
c.globalThis.eval = c.globalThis.Function = function() {
Copy link
Contributor

Choose a reason for hiding this comment

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

All the *Function constructors reachable by somePrototype.constructor are inert. They only throw. They don't do tamed evaluation.

The only *Function constructor that has ever been reachable any other way is the Function constructor itself, by name from the global object. Thus, by default, that one is a tamed evaluator.

Besides eval and Function, we have one other per-compartment global evaluator: Compartment.prototype.evaluate. If we want to turn off all evaluators in a compartment, we need to turn that one off as well.

@kriskowal kriskowal dismissed mhofman’s stale review February 22, 2022 15:09

We have agreed out-of-band that to keep the compartment evaluator behavior as written.

@kriskowal kriskowal enabled auto-merge (squash) February 22, 2022 15:10
@kriskowal kriskowal merged commit 735ff94 into endojs:master Feb 22, 2022
@Jack-Works Jack-Works deleted the eval-taming branch February 22, 2022 15:32
@Jack-Works
Copy link
Contributor Author

Cool!

erights added a commit that referenced this pull request Mar 12, 2025
Closes: #XXXX
Refs: #961 #2690 #2723

## Description

#961 deviated from our general convention that lockdown option values be
kebob-case, instead adding `evalTaming:` option values `safeEval`,
`unsafeEval`, `noEval`. (I approved #961 at the time, apparently without
noticing this discrepancy.) This PR fixes those to be `safe-eval`,
`unsafe-eval`, and `no-eval`. But to avoid breaking any old usage, this
PR ensure the only names continue to work for now, but always commented
in the code as "deprecated".

This PR does only that. Other changes to the relevant lockdown option or
relevant lockdown options machinery are left to #2723 or #2690
respectively. I request that this PR go first, with those others
adjusting to this one.

### Security Considerations

none
### Scaling Considerations

non
### Documentation Considerations

This PR simply changes the documentation to use the new names without
ever mentioning the deprecated old names. That seems like an appropriate
simplification for the docs.

### Testing Considerations

With a bit of duplication and renaming, we now test the new names and
the old deprecated names.

### Compatibility Considerations

To avoid breaking any old usage, this PR ensure the only names continue
to work for now, but always commented in the code as "deprecated". It
would be very nice to eventually be able to retire the deprecated names,
but I find it hard to imagine how we'd test that it is safe to do so.

### Upgrade Considerations

Nothing BREAKING, since the old deprecated names continue to work.

- [x] Update `NEWS.md` for user-facing changes.
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.

4 participants