Skip to content

Commit

Permalink
docs(ses): Document vetted shims
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Aug 21, 2023
1 parent e3e8a7e commit fb969cb
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 10 deletions.
8 changes: 8 additions & 0 deletions packages/ses/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
User-visible changes in SES:

# Next

- Extracts `repairIntrinsics(options)` and `hardenIntrinsics()` from the
behavior of `lockdown(options)` so vetted shims can run between these
calls.
Any modifications to shared intrinsics survive if applied after
`repairIntrinsics()`.

# v0.18.6 (2023-08-07)

- Censors the pattern `{...import(specifier)`}.
Expand Down
95 changes: 85 additions & 10 deletions packages/ses/docs/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Hardened JavaScript:
- Removes non-determinism by modifying a few built-in objects.
- Adds functionality to freeze and make immutable both built-in JavaScript
objects and program created objects and make them immutable.
- Is (as SES) is a proposed extension to the JavaScript standard.
- Is (tentatively named SES) a proposed extension to the JavaScript standard.

Hardened JavaScript consists of three parts:
- Lockdown is a function that irreversibly repairs and hardens an existing
Expand All @@ -39,6 +39,13 @@ Hardened JavaScript consists of three parts:
globals and modules, but shared hardened primordials and limited access to
other powerful objects in global scope.

And, Lockdown consists of separable Repair Intrinsics and Harden Intrinsics
phases, so that shims (other programs that alter JavaScript) may run between
them.
These shims are obliged to maintain the object capability safety invariants
provided by Lockdown and must be carefully reviewed.
We call these "vetted shims".

## What is SES?

SES is an old umbrella term for the Hardened JavaScript effort, and while we
Expand Down Expand Up @@ -143,6 +150,45 @@ To use SES as a script on the web, use the UMD build.
<script src="node_modules/ses/dist/ses.umd.min.js">
```

## Using Hardened JavaScript with vetted shims

Some modules depend on language features that may not be present in the
underlying platform.
Some of these shims will compose poorly with `lockdown()`.
Lockdown will remove any property it finds on a shared intrinsic (like
`Array.prototype`) that it does not recognize and then freeze all the shared
intrinsics and all the objects transitively reachable through own properties
and prototypes.

So, if a shim adds `Array.prototype.collate`, running that shim before calling
`lockdown()` will have no net effect and running this shim after calling
`lockdown()` will throw an exception when attempting to assign or define that
property.

Lockdown consists of two phases: Repair Intrinsics and Harden Intrinsics.
A shim can run between these phases and its effects will persist.
The following programs are equivalent:

```js
lockdown(options);
```

And,

```js
repairIntrinsics(options);
hardenIntrinsics();
```

And, an application that choses to call these also has the option of running
shims between the two phases.

However, any such shim must preserve the qualities of Lockdown:
all reachable objects in an empty compartment must be hardened and must not
provide a way for isolated parties to communicate.
So, application authors are responsible for ensuring these shims maintain their
application’s integrity invariants.

## What Lockdown does to JavaScript

Hardened JavaScript does not include any I/O objects providing "unsafe" [*ambient authority*](https://en.wikipedia.org/wiki/Ambient_authority).
Expand Down Expand Up @@ -199,7 +245,7 @@ Most Node.js-specific [global objects](https://nodejs.org/dist/latest-v14.x/docs
* `WebAssembly`
* `TextEncoder` and `TextDecoder`
* `global`
* Use `globalThis` instead (and remember it is frozen).
* Use `globalThis` instead.
* `process`
* No `process.env` to access the process's environment variables.
* No `process.argv` for the argument array.
Expand Down Expand Up @@ -239,15 +285,29 @@ makes those global objects available.
and defer the construction of error objects and computed messages until an
assertion fails.

- `lockdown()` and `harden()` both freeze an object’s API surface (enumerable data properties).
A hardened object’s properties cannot be changed, only read, so the only way to interact with a
hardened object is through its methods. `harden()` is similar to `Object.freeze()` but more
thorough. See the individual [`lockdown()`](#lockdown) and [`harden()`](#harden) sections
below.
- `repairIntrinsics` adds, removes, and replaces various properties of the
global environment and shared intrinsics.
Introduces `hardenIntrinsics`.

- `hardenIntrinsics` freezes the transitive own properties and prototypes of
the shared intrinsics.
Introduces `harden`.

- [`harden()`](#harden) provides a shorthand for reliably freezing the
transitive properties and prototypes of other objects, such that the API
surface of these objects are tamper-proof when shared between otherwise
isolated programs.

- [`Compartment`](https://github.com/endojs/endo/tree/SES-v0.8.0/packages/ses#compartment) is
a global. Code runs inside a `Compartment` and can create sub-compartments to host other
code (with different globals or transforms). Note that these child compartments get `harden()` and `Compartment`.
- [`lockdown()`](#lockdown) is a shorthand for `repairIntrinsics` and `hardenIntrinsics`.

- [`Compartment`](https://github.com/endojs/endo/tree/SES-v0.8.0/packages/ses#compartment)
Code runs inside a `Compartment` and can create sub-compartments to host
other code (with different globals or code transforms).
The globals in a child compartment include the shared intrinsics including
`harden` and a batch of evaluators that run programs that will also be
confined to the compartment including `eval`, `Function`, and `Compartment`
itself.
Compartments also load and confine modules.

## Realms

Expand Down Expand Up @@ -410,6 +470,21 @@ some covert communication channels).
For a full explanation of `lockdown()` and its options, please click
[here](./lockdown.md).

## `repairIntrinsics()`

Performs the first part of Lockdown: adding, removing, and replacing certain
JavaScript intrinsics so that some intrinsics can be safely shared between
confined programs.
Running `repairIntrinsics()` introduces `hardenIntrinsics()`.

## `hardenIntrinsics()`

Performs the last part of Lockdown: hardening the shared intrinsics so they can
be safely shared between confined programs.
Running `hardenIntrinsics()` reveals the `harden()` function.
(Harden is not useful until after `hardenIntrinsics()` and could interfere with
the execution of repairs or shims if it were revealed earlier.)

## `harden()`

`harden()` is automatically provided by `lockdown()`. Any code that will run inside a vat or a
Expand Down
16 changes: 16 additions & 0 deletions packages/ses/docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ To use SES as a script on the web, use the UMD build.
<script src="node_modules/ses/dist/ses.umd.min.js">
```

To run shims after `ses` repairs the intrinsics but before `ses` hardens the
intrinsics, calling `lockdown(options)` is equivalent to running
`repairIntrinsics(options)` then `hardenIntrinsics()` and vetted shims can run
in between.
```js
import './non-ses-code-before-lockdown.js';
import './ses-repair-intrinsics.js'; // calls repairIntrinsics.
import './vetted-shim.js';
import './ses-harden-intrinsics.js'; // calls repairIntrinsics.
import './ses-code-after-lockdown.js';
```

SES is vulnerable to any code that runs before hardening intrinsics.
All such code, including vetted shims, must receive careful review to ensure it
preserves the invariants of the OCap security model.

## Removed by Hardened JavaScript summary

The following are missing or unusable under Hardened JavaScript:
Expand Down

0 comments on commit fb969cb

Please sign in to comment.