-
Notifications
You must be signed in to change notification settings - Fork 74
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
docs(ses): Document environment lockdown options #2018
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,24 +20,39 @@ compatibility vs better tool compatibility. | |
|
||
Each option is explained in its own section below. | ||
|
||
| option | default setting | other settings | about | | ||
|--------------------|------------------|----------------|-------| | ||
| `regExpTaming` | `'safe'` | `'unsafe'` | `RegExp.prototype.compile` | | ||
| `localeTaming` | `'safe'` | `'unsafe'` | `toLocaleString` | | ||
| `consoleTaming` | `'safe'` | `'unsafe'` | deep stacks | | ||
| `errorTaming` | `'safe'` | `'unsafe'` | `errorInstance.stack` | | ||
| `errorTrapping` | `'platform'` | `'exit'` `'abort'` `'report'` `'none'` | handling of uncaught exceptions | | ||
| `unhandledRejectionTrapping` | `'report'` | `'none'` | handling of finalized unhandled rejections | | ||
| `evalTaming` | `'safeEval'` | `'unsafeEval'` `'noEval'` | `eval` and `Function` of the start compartment. | | ||
| `stackFiltering` | `'concise'` | `'verbose'` | deep stacks signal/noise | | ||
| `overrideTaming` | `'moderate'` | `'min'` or `'severe'` | override mistake antidote | | ||
| `overrideDebug` | `[]` | array of property names | detect override mistake | | ||
| `domainTaming` | `'safe'` | `'unsafe'` | Node.js `domain` module | | ||
| `__hardenTaming__` | `'safe'` | `'unsafe'` | Making `harden` no-op for performance in trusted environments | | ||
| option | default setting | other settings | about | | ||
|------------------------------|------------------|----------------------------------------|-------| | ||
| `regExpTaming` | `'safe'` | `'unsafe'` | `RegExp.prototype.compile` | | ||
| `localeTaming` | `'safe'` | `'unsafe'` | `toLocaleString` | | ||
| `consoleTaming` | `'safe'` | `'unsafe'` | deep stacks | | ||
| `errorTaming` | `'safe'` | `'unsafe'` | `errorInstance.stack` | | ||
| `errorTrapping` | `'platform'` | `'exit'` `'abort'` `'report'` `'none'` | handling of uncaught exceptions | | ||
| `unhandledRejectionTrapping` | `'report'` | `'none'` | handling of finalized unhandled rejections | | ||
| `evalTaming` | `'safeEval'` | `'unsafeEval'` `'noEval'` | `eval` and `Function` of the start compartment. | | ||
| `stackFiltering` | `'concise'` | `'verbose'` | deep stacks signal/noise | | ||
| `overrideTaming` | `'moderate'` | `'min'` or `'severe'` | override mistake antidote | | ||
| `overrideDebug` | `[]` | array of property names | detect override mistake | | ||
| `domainTaming` | `'safe'` | `'unsafe'` | Node.js `domain` module | | ||
| `__hardenTaming__` | `'safe'` | `'unsafe'` | Making `harden` no-op for performance in trusted environments | | ||
|
||
In the absence of any of these options in lockdown arguments, lockdown will | ||
attempt to read these from the Node.js `process.env` environment. | ||
The corresponding environment variables are the same but in `UPPER_SNAKE_CASE`. | ||
attempt to read these options from `process.env`, using the Node.js convention | ||
for threading environment variables into a JavaScript program. | ||
|
||
| option | environment variable | notes | | ||
|------------------------------|-----------------------------------------|-----------------------| | ||
| `regExpTaming` | `LOCKDOWN_REGEXP_TAMING` | | | ||
| `localeTaming` | `LOCKDOWN_LOCALE_TAMING` | | | ||
| `consoleTaming` | `LOCKDOWN_CONSOLE_TAMING` | | | ||
| `errorTaming` | `LOCKDOWN_ERROR_TAMING` | | | ||
| `errorTrapping` | `LOCKDOWN_ERROR_TRAPPING` | | | ||
| `unhandledRejectionTrapping` | `LOCKDOWN_UNHANDLED_REJECTION_TRAPPING` | | | ||
| `evalTaming` | `LOCKDOWN_EVAL_TAMING` | | | ||
| `stackFiltering` | `LOCKDOWN_STACK_FILTERING` | | | ||
| `overrideTaming` | `LOCKDOWN_OVERRIDE_TAMING` | | | ||
| `overrideDebug` | `LOCKDOWN_OVERRIDE_DEBUG` | comma separated names | | ||
| `domainTaming` | `LOCKDOWN_DOMAIN_TAMING` | | | ||
| `__hardenTaming__` | `LOCKDOWN_HARDEN_TAMING` | | | ||
|
||
The options `mathTaming` and `dateTaming` are deprecated. | ||
`Math.random`, `Date.now`, and the `new Date()` are disabled within | ||
|
@@ -73,6 +88,14 @@ lockdown({ regExpTaming: 'safe' }); // Delete RegExp.prototype.compile | |
lockdown({ regExpTaming: 'unsafe' }); // Preserve RegExp.prototype.compile | ||
``` | ||
|
||
If `lockdown` does not receive a `regExpTaming` option, it will respect | ||
`process.env.LOCKDOWN_REGEXP_TAMING`. | ||
|
||
```console | ||
LOCKDOWN_REGEXP_TAMING=safe | ||
LOCKDOWN_REGEXP_TAMING=unsafe | ||
``` | ||
|
||
The `regExpTaming` default `'safe'` setting deletes this dangerous method. The | ||
`'unafe'` setting preserves it for maximal compatibility at the price of some | ||
risk. | ||
|
@@ -121,6 +144,14 @@ lockdown({ localeTaming: 'safe' }); // Alias toLocaleString to toString, etc | |
lockdown({ localeTaming: 'unsafe' }); // Allow locale-specific behavior | ||
``` | ||
|
||
If `lockdown` does not receive a `localeTaming` option, it will respect | ||
`process.env.LOCKDOWN_LOCALE_TAMING`. | ||
|
||
```console | ||
LOCKDOWN_LOCALE_TAMING=safe | ||
LOCKDOWN_LOCALE_TAMING=unsafe | ||
``` | ||
|
||
The `localeTaming` default `'safe'` option replaces each of these methods with | ||
the corresponding non-locale-specific method. `Object.prototype.toLocaleString` | ||
becomes just another name for `Object.prototype.toString`. The `'unsafe'` | ||
|
@@ -166,17 +197,35 @@ lockdown({ | |
overrideTaming: 'min', // Until https://github.com/endojs/endo/issues/636 | ||
}); | ||
``` | ||
|
||
If `lockdown` does not receive a `consoleTaming` option, it will respect | ||
`process.env.LOCKDOWN_CONSOLE_TAMING`. | ||
|
||
```console | ||
LOCKDOWN_CONSOLE_TAMING=safe | ||
LOCKDOWN_CONSOLE_TAMING=unsafe | ||
``` | ||
|
||
The `consoleTaming: 'safe'` setting replaces the global console with a tamed | ||
console, and that tamed console is safe to endow to a guest `Compartment`. | ||
Additionally, any errors created with the `assert` function or methods on its | ||
namespace may have [redacted details](../src/error/README.md): information | ||
included in the error message that is informative to a debugger and made | ||
invisible to an attacker. | ||
The tamed console removes redactions and shows these details to the original | ||
console. | ||
|
||
The `consoleTaming: 'unsafe'` setting leaves the original console in place. | ||
The `assert` package and error objects will continue to work, but the `console` | ||
logging output will not show any of this extra information. | ||
|
||
The risk is that the original platform-provided `console` object often has | ||
additional methods beyond the de facto `console` "standards". Under the | ||
`'unsafe'` setting we do not remove them. | ||
We do not know whether any of these additional | ||
methods violate ocap security. Until we know otherwise, we should assume these | ||
are unsafe. Such a raw `console` object should only be handled by very | ||
trustworthy code. | ||
additional methods beyond the de facto `console` "standards" and may be unsafe | ||
to endow to a guest `Compartment`. | ||
Under the `'unsafe'` setting we do not remove them. | ||
We do not know whether any of these additional methods violate ocap security. | ||
Until we know otherwise, we should assume these are unsafe. Such a raw | ||
`console` object should only be handled by very trustworthy code. | ||
|
||
Until the bug | ||
[Node console gets confused if .constructor is an accessor (#636)](https://github.com/endojs/endo/issues/636) | ||
|
@@ -267,6 +316,14 @@ lockdown({ errorTaming: 'safe' }); // Deny unprivileged access to stacks, if pos | |
lockdown({ errorTaming: 'unsafe' }); // stacks also available by errorInstance.stack | ||
``` | ||
|
||
If `lockdown` does not receive an `errorTaming` option, it will respect | ||
`process.env.LOCKDOWN_ERROR_TAMING`. | ||
|
||
```console | ||
LOCKDOWN_ERROR_TAMING=safe | ||
LOCKDOWN_ERROR_TAMING=unsafe | ||
``` | ||
|
||
The `errorTaming` default `'safe'` setting makes the stack trace inaccessible | ||
from error instances alone, when possible. It currently does this only on | ||
v8 (Chrome, Brave, Node). It will also do so on SpiderMonkey (Firefox). | ||
|
@@ -336,6 +393,17 @@ lockdown({ errorTrapping: 'report' }); // just report | |
lockdown({ errorTrapping: 'none' }); // no platform error traps | ||
``` | ||
|
||
If `lockdown` does not receive an `errorTrapping` option, it will respect | ||
`process.env.LOCKDOWN_ERROR_TRAPPING`. | ||
|
||
```console | ||
LOCKDOWN_ERROR_TRAPPING=platform | ||
LOCKDOWN_ERROR_TRAPPING=exit | ||
LOCKDOWN_ERROR_TRAPPING=abort | ||
LOCKDOWN_ERROR_TRAPPING=report | ||
LOCKDOWN_ERROR_TRAPPING=none | ||
``` | ||
|
||
On the web, the `window` event emitter has a trap for `error` events. | ||
In the absence of a trap, the platform logs the error to the debugger console | ||
and continues. | ||
|
@@ -383,6 +451,14 @@ lockdown({ unhandledRejectionTrapping: 'report' }); // print finalized unhandled | |
lockdown({ unhandledRejectionTrapping: 'none' }); // no special unhandled rejection traps | ||
``` | ||
|
||
If `lockdown` does not receive an `unhandledRejectionTrapping` option, it will | ||
respect `process.env.LOCKDOWN_UNHANDLED_REJECTION_TRAPPING`. | ||
|
||
```console | ||
LOCKDOWN_UNHANDLED_REJECTION_TRAPPING=report | ||
LOCKDOWN_UNHANDLED_REJECTION_TRAPPING=none | ||
``` | ||
|
||
On the web, the `window` event emitter has a trap for `unhandledrejection` and | ||
`rejectionhandled` events. In the absence of a trap, the platform logs | ||
rejections that were not handled in the same turn in which they were created to | ||
|
@@ -410,13 +486,14 @@ triggering the SES trap handler. | |
|
||
This option only affects the start compartment! | ||
|
||
To disallows eval in the explicit compartments, replace the constructors in the compartment. | ||
To disallow `eval` in specific compartments, replace `eval` and the function | ||
constructors in the compartment. | ||
|
||
```js | ||
const c = new Compartment() | ||
c.globalThis.eval = c.globalThis.Function = function() { | ||
throw new TypeError() | ||
} | ||
throw new TypeError(); | ||
}; | ||
Comment on lines
+495
to
+496
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too bad eslint doesn't run on "```js" blocks in .md files ;) |
||
``` | ||
|
||
**Background**: Every realm has an implicit initial compartment we call the "start compartment". Explicit compartments are made with the `Compartment` constructor. | ||
|
@@ -459,6 +536,15 @@ lockdown({ evalTaming: 'noEval' }); // disallowing calling eval like there is a | |
lockdown({ evalTaming: 'unsafeEval' }); | ||
``` | ||
|
||
If `lockdown` does not receive an `evalTaming` option, it will respect | ||
`process.env.LOCKDOWN_EVAL_TAMING`. | ||
|
||
```console | ||
LOCKDOWN_EVAL_TAMING=safeEval | ||
LOCKDOWN_EVAL_TAMING=noEval | ||
LOCKDOWN_EVAL_TAMING=unsafeEval | ||
``` | ||
|
||
## `stackFiltering` Options | ||
|
||
**Background**: The error stacks shown by many JavaScript engines are | ||
|
@@ -480,6 +566,14 @@ lockdown({ stackFiltering: 'concise' }); // Preserve important deep stack info | |
lockdown({ stackFiltering: 'verbose' }); // Console shows full deep stacks | ||
``` | ||
|
||
If `lockdown` does not receive a `stackFiltering` option, it will respect | ||
`process.env.LOCKDOWN_STACK_FILTERING`. | ||
|
||
```console | ||
LOCKDOWN_STACK_FILTERING=concise | ||
LOCKDOWN_STACK_FILTERING=verbose | ||
``` | ||
|
||
When looking at deep distributed stacks, in order to debug distributed | ||
computation, seeing the full stacks is overwhelmingly noisy. The error stack | ||
proposal leaves it to the host what stack trace info to show. SES virtualizes | ||
|
@@ -617,6 +711,15 @@ lockdown({ overrideTaming: 'min' }); // Minimal mitigations for purely modern co | |
lockdown({ overrideTaming: 'severe' }); // More severe legacy compat | ||
``` | ||
|
||
If `lockdown` does not receive a `overrideTaming` option, it will respect | ||
`process.env.LOCKDOWN_OVERRIDE_TAMING`. | ||
|
||
```console | ||
LOCKDOWN_OVERRIDE_TAMING=moderate | ||
LOCKDOWN_OVERRIDE_TAMING=min | ||
LOCKDOWN_OVERRIDE_TAMING=severe | ||
``` | ||
|
||
The `overrideTaming` default `'moderate'` option of `lockdown` is intended to | ||
be fairly minimal, but we expand it as needed, when we | ||
encounter code which should run under SES but is prevented from doing so | ||
|
@@ -661,9 +764,11 @@ by our override mitigation. | |
|
||
## `overrideDebug` Options | ||
|
||
To help diagnose problems with the override mistake, you can set this option to | ||
a list of properties that will print diagnostic information when their override | ||
enablement is triggered. | ||
To help diagnose problems with the [Property Override Mistake][POM], you can | ||
set this option to a list of properties that will print diagnostic information | ||
when their override enablement is triggered. | ||
|
||
[POM]: https://github.com/endojs/endo/discussions/1855 | ||
|
||
For example, to find the client code that causes a `constructor` property override | ||
mistake, set the options as follows: | ||
|
@@ -675,12 +780,24 @@ mistake, set the options as follows: | |
} | ||
``` | ||
|
||
If `lockdown` does not receive a `regExpTaming` option, it will respect | ||
`process.env.LOCKDOWN_OVERRIDE_DEBUG`, a comma-separated list of property names | ||
on shared intrinsics to replace with debugger accessors. | ||
|
||
```console | ||
LOCKDOWN_OVERRIDE_DEBUG=constructor,toString | ||
``` | ||
|
||
The idiom for `@agoric/install-ses` when tracking down the override | ||
mistake with the `constructor` property is to set the following | ||
environment variable: | ||
|
||
```sh | ||
LOCKDOWN_OPTIONS='{"errorTaming":"unsafe","stackFiltering":"verbose","overrideTaming":"severe","overrideDebug":["constructor"]}' | ||
LOCKDOWN_ERROR_TAMING=unsafe \ | ||
LOCKDOWN_STACK_FILTERING=verbose \ | ||
LOCKDOWN_OVERRIDE_TAMING=severe \ | ||
LOCKDOWN_OVERRIDE_DEBUG=constructor \ | ||
node ... | ||
``` | ||
|
||
Then, when some script deep in the require stack does: | ||
|
@@ -748,6 +865,14 @@ lockdown({ __hardenTaming__: 'safe' }); // harden works | |
lockdown({ __hardenTaming__: 'unsafe' }); // harden is noop. Other tests pretend | ||
``` | ||
|
||
If `lockdown` does not receive a `__hardenTaming__` option, it will respect | ||
`process.env.LOCKDOWN_HARDEN_TAMING`. | ||
|
||
```console | ||
LOCKDOWN_HARDEN_TAMING=safe | ||
LOCKDOWN_HARDEN_TAMING=unsafe | ||
``` | ||
|
||
We created this option specifically for | ||
speed of the SwingSet kernel. It could also be used for other highly vetted, style | ||
restricted, security-critical, and speed-critical code. This would be safe to turn | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI
endo/packages/ses/src/lockdown.js
Lines 312 to 314 in 193e403