Comparing version 0.15.12 to 0.15.13
@@ -6,2 +6,12 @@ # Change Log | ||
### [0.15.13](https://github.com/endojs/endo/compare/ses@0.15.12...ses@0.15.13) (2022-04-13) | ||
### Bug Fixes | ||
* Revert dud release ([c8a7101](https://github.com/endojs/endo/commit/c8a71017d8d7af10a97909c9da9c5c7e59aed939)) | ||
* **ses:** Prevent hypothetical stack bumping to get unsafe eval ([3c64cde](https://github.com/endojs/endo/commit/3c64cdea5b410a053520dc29de04c43350a38e1a)), closes [#956](https://github.com/endojs/endo/issues/956) | ||
### [0.15.12](https://github.com/endojs/endo/compare/ses@0.15.11...ses@0.15.12) (2022-04-12) | ||
@@ -8,0 +18,0 @@ |
{ | ||
"name": "ses", | ||
"version": "0.15.12", | ||
"version": "0.15.13", | ||
"description": "Hardened JavaScript for Fearless Cooperation", | ||
@@ -62,6 +62,6 @@ "keywords": [ | ||
"devDependencies": { | ||
"@endo/compartment-mapper": "^0.7.2", | ||
"@endo/eslint-config": "^0.4.7", | ||
"@endo/static-module-record": "^0.7.1", | ||
"@endo/test262-runner": "^0.1.23", | ||
"@endo/compartment-mapper": "^0.7.3", | ||
"@endo/eslint-config": "^0.4.8", | ||
"@endo/static-module-record": "^0.7.2", | ||
"@endo/test262-runner": "^0.1.24", | ||
"ava": "^3.12.1", | ||
@@ -183,3 +183,3 @@ "babel-eslint": "^10.0.3", | ||
}, | ||
"gitHead": "59e511891ab67f4fa52d67141510974e22362134" | ||
"gitHead": "ada5203fd64e6828dca74895fd74588e08925d97" | ||
} |
@@ -58,3 +58,3 @@ /// <reference types="ses"> | ||
globalObject, | ||
localObject, | ||
globalLexicals: localObject, | ||
globalTransforms, | ||
@@ -61,0 +61,0 @@ sloppyGlobalsMode, |
@@ -286,3 +286,3 @@ // @ts-check | ||
globalObject, | ||
localObject: globalLexicals, | ||
globalLexicals, | ||
globalTransforms, | ||
@@ -289,0 +289,0 @@ sloppyGlobalsMode: false, |
@@ -19,4 +19,2 @@ // Portions adapted from V8 - Copyright 2016 the V8 project authors. | ||
// TODO: rename localObject to scopeObject | ||
/** | ||
@@ -29,3 +27,3 @@ * makeSafeEvaluator() | ||
* @param {Object} options.globalObject | ||
* @param {Object} [options.localObject] | ||
* @param {Object} [options.globalLexicals] | ||
* @param {Array<Transform>} [options.globalTransforms] | ||
@@ -37,3 +35,3 @@ * @param {bool} [options.sloppyGlobalsMode] | ||
globalObject, | ||
localObject = {}, | ||
globalLexicals = {}, | ||
globalTransforms = [], | ||
@@ -43,9 +41,9 @@ sloppyGlobalsMode = false, | ||
} = {}) => { | ||
const { | ||
scopeHandler, | ||
admitOneUnsafeEvalNext, | ||
resetOneUnsafeEvalNext, | ||
} = createScopeHandler(globalObject, localObject, { | ||
sloppyGlobalsMode, | ||
}); | ||
const { scopeHandler, scopeController } = createScopeHandler( | ||
globalObject, | ||
globalLexicals, | ||
{ | ||
sloppyGlobalsMode, | ||
}, | ||
); | ||
const { proxy: scopeProxy, revoke: revokeScopeProxy } = proxyRevocable( | ||
@@ -63,3 +61,3 @@ immutableObject, | ||
if (!evaluate) { | ||
const constants = getScopeConstants(globalObject, localObject); | ||
const constants = getScopeConstants(globalObject, globalLexicals); | ||
const evaluateFactory = makeEvaluateFactory(constants); | ||
@@ -86,3 +84,3 @@ evaluate = apply(evaluateFactory, scopeProxy, []); | ||
admitOneUnsafeEvalNext(); | ||
scopeController.allowNextEvalToBeUnsafe = true; | ||
let err; | ||
@@ -97,9 +95,11 @@ try { | ||
} finally { | ||
if (resetOneUnsafeEvalNext()) { | ||
const unsafeEvalWasStillExposed = scopeController.allowNextEvalToBeUnsafe; | ||
scopeController.allowNextEvalToBeUnsafe = false; | ||
if (unsafeEvalWasStillExposed) { | ||
// Barring a defect in the SES shim, the scope proxy should allow the | ||
// powerful, unsafe `eval` to be used by `evaluate` exactly once, as the | ||
// very first name that it attempts to access from the lexical scope. | ||
// A defect in the SES shim could throw an exception after our call to | ||
// `admitOneUnsafeEvalNext()` and before `evaluate` calls `eval` | ||
// internally. | ||
// A defect in the SES shim could throw an exception after we set | ||
// `scopeController.allowNextEvalToBeUnsafe` and before `evaluate` | ||
// calls `eval` internally. | ||
// If we get here, SES is very broken. | ||
@@ -106,0 +106,0 @@ // This condition is one where this vat is now hopelessly confused, and |
@@ -15,2 +15,3 @@ import { | ||
reflectSet, | ||
seal, | ||
} from './commons.js'; | ||
@@ -57,3 +58,3 @@ import { assert } from './error/assert.js'; | ||
globalObject, | ||
localObject = {}, | ||
globalLexicals = {}, | ||
{ sloppyGlobalsMode = false } = {}, | ||
@@ -64,14 +65,12 @@ ) => { | ||
// differently. | ||
let allowNextEvalToBeUnsafe = false; | ||
const admitOneUnsafeEvalNext = () => { | ||
allowNextEvalToBeUnsafe = true; | ||
// Using a flag on an object with a single mutable property allows a safe | ||
// evaluator to signal to the scope proxy without consuming a stack frame. | ||
// Consuming a stack frame could possibly allow an attacker to control the | ||
// stack depth before calling `evaluate` to cause a RangeError before this | ||
// flag can be reset, leaving the unsafe evaluator available. | ||
const scopeController = { | ||
allowNextEvalToBeUnsafe: false, | ||
}; | ||
seal(scopeController); | ||
const resetOneUnsafeEvalNext = () => { | ||
const wasSet = allowNextEvalToBeUnsafe; | ||
allowNextEvalToBeUnsafe = false; | ||
return wasSet; | ||
}; | ||
const scopeProxyHandlerProperties = { | ||
@@ -88,5 +87,5 @@ get(_shadow, prop) { | ||
// test that it is true rather than merely truthy | ||
if (allowNextEvalToBeUnsafe === true) { | ||
if (scopeController.allowNextEvalToBeUnsafe === true) { | ||
// revoke before use | ||
allowNextEvalToBeUnsafe = false; | ||
scopeController.allowNextEvalToBeUnsafe = false; | ||
return FERAL_EVAL; | ||
@@ -97,8 +96,8 @@ } | ||
// Properties of the localObject. | ||
if (prop in localObject) { | ||
// Properties of the globalLexicals. | ||
if (prop in globalLexicals) { | ||
// Use reflect to defeat accessors that could be present on the | ||
// localObject object itself as `this`. | ||
// globalLexicals object itself as `this`. | ||
// This is done out of an overabundance of caution, as the SES shim | ||
// only use the localObject carry globalLexicals and live binding | ||
// only use the globalLexicals carry globalLexicals and live binding | ||
// traps. | ||
@@ -112,3 +111,3 @@ // The globalLexicals are captured as a snapshot of what's passed to | ||
// receiver. | ||
return reflectGet(localObject, prop, globalObject); | ||
return reflectGet(globalLexicals, prop, globalObject); | ||
} | ||
@@ -121,13 +120,13 @@ | ||
set(_shadow, prop, value) { | ||
// Properties of the localObject. | ||
if (prop in localObject) { | ||
const desc = getOwnPropertyDescriptor(localObject, prop); | ||
// Properties of the globalLexicals. | ||
if (prop in globalLexicals) { | ||
const desc = getOwnPropertyDescriptor(globalLexicals, prop); | ||
if (objectHasOwnProperty(desc, 'value')) { | ||
// Work around a peculiar behavior in the specs, where | ||
// value properties are defined on the receiver. | ||
return reflectSet(localObject, prop, value); | ||
return reflectSet(globalLexicals, prop, value); | ||
} | ||
// Ensure that the 'this' value on setters resolves | ||
// to the safeGlobal, not to the localObject object. | ||
return reflectSet(localObject, prop, value, globalObject); | ||
// to the safeGlobal, not to the globalLexicals object. | ||
return reflectSet(globalLexicals, prop, value, globalObject); | ||
} | ||
@@ -175,4 +174,4 @@ | ||
sloppyGlobalsMode || | ||
(allowNextEvalToBeUnsafe && prop === 'eval') || | ||
prop in localObject || | ||
(scopeController.allowNextEvalToBeUnsafe && prop === 'eval') || | ||
prop in globalLexicals || | ||
prop in globalObject || | ||
@@ -217,6 +216,5 @@ prop in globalThis | ||
return { | ||
admitOneUnsafeEvalNext, | ||
resetOneUnsafeEvalNext, | ||
scopeController, | ||
scopeHandler, | ||
}; | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2715194
57199