| import { Object, DataView, Reflect, Number } from './commons.js'; | ||
| const { is, defineProperty, entries } = Object; | ||
| const { apply } = Reflect; | ||
| const { prototype: dataViewPrototype } = DataView; | ||
| /** | ||
| * These `FERAL*` methods open up the NaN side-channel on some platforms, | ||
| * like v8. Thus, we need to encapsulate them and replace them with wrappers | ||
| * that canonicaize NaNs. | ||
| */ | ||
| const { | ||
| setFloat16: FERAL_SET_FLOAT16, | ||
| setFloat32: FERAL_SET_FLOAT32, | ||
| setFloat64: FERAL_SET_FLOAT64, | ||
| setUint16, | ||
| setUint32, | ||
| setBigUint64, | ||
| } = dataViewPrototype; | ||
| // See https://webidl.spec.whatwg.org/#js-unrestricted-double which implies | ||
| // that this is the canonical NaN for web standards. | ||
| // Casual googling stongly suggests that this is also the cosmWasm | ||
| // canonical NaN. But I have not yet found an authoritative page stating this. | ||
| const canonicalNaN = 0x7ff8000000000000n; | ||
| // Use method shorthand syntax to be this-sensitive but now be constructable | ||
| // nor have a `prototype` property. | ||
| const methods = { | ||
| /** | ||
| * @param {number} byteOffset | ||
| * @param {number} value | ||
| * @param {boolean} [littleEndian] | ||
| */ | ||
| setFloat16(byteOffset, value, littleEndian = undefined) { | ||
| if (is(value, NaN)) { | ||
| return apply(setUint16, this, [ | ||
| byteOffset, | ||
| Number(canonicalNaN), | ||
| littleEndian, | ||
| ]); | ||
| } else { | ||
| return apply(FERAL_SET_FLOAT16, this, [byteOffset, value, littleEndian]); | ||
| } | ||
| }, | ||
| /** | ||
| * @param {number} byteOffset | ||
| * @param {number} value | ||
| * @param {boolean} [littleEndian] | ||
| */ | ||
| setFloat32(byteOffset, value, littleEndian = undefined) { | ||
| if (is(value, NaN)) { | ||
| return apply(setUint32, this, [ | ||
| byteOffset, | ||
| Number(canonicalNaN), | ||
| littleEndian, | ||
| ]); | ||
| } else { | ||
| return apply(FERAL_SET_FLOAT32, this, [byteOffset, value, littleEndian]); | ||
| } | ||
| }, | ||
| /** | ||
| * @param {number} byteOffset | ||
| * @param {number} value | ||
| * @param {boolean} [littleEndian] | ||
| */ | ||
| setFloat64(byteOffset, value, littleEndian = undefined) { | ||
| if (is(value, NaN)) { | ||
| return apply(setBigUint64, this, [ | ||
| byteOffset, | ||
| canonicalNaN, | ||
| littleEndian, | ||
| ]); | ||
| } else { | ||
| return apply(FERAL_SET_FLOAT64, this, [byteOffset, value, littleEndian]); | ||
| } | ||
| }, | ||
| }; | ||
| /** | ||
| * Replaces the dangerous `setFloat*` methods on `DataView.prototype` | ||
| * with safe wrappers that first canonicalize NaNs before calling the | ||
| * original hidden methods. | ||
| * By itself, this does not make us safe against the NaN side channel. | ||
| * Separately, we do not include the `Float*Array` constructors on the | ||
| * list of universal safe globals. Thus, constructed compartments do not | ||
| * get these by default. | ||
| * | ||
| * These replacement `setFloat*` methods canonicalize NaN, but they | ||
| * do not canonicalize `-0` to `0`. If callers wish to do so, they should do | ||
| * it themselves before calling these | ||
| */ | ||
| export const tameNaNSideChannel = () => { | ||
| for (const [name, method] of entries(methods)) { | ||
| defineProperty(dataViewPrototype, name, { | ||
| // Since we're redefining properties that already exist, by omitting the | ||
| // other descriptor attributes here, they are unchanged. | ||
| value: method, | ||
| }); | ||
| } | ||
| }; |
+7
-7
| { | ||
| "name": "ses", | ||
| "version": "1.15.0", | ||
| "version": "2.0.0", | ||
| "description": "Hardened JavaScript for Fearless Cooperation", | ||
@@ -94,3 +94,3 @@ "keywords": [ | ||
| "test:xs": "xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp", | ||
| "postpack": "git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\"" | ||
| "postpack": "git clean -fX -e node_modules/" | ||
| }, | ||
@@ -107,5 +107,5 @@ "dependencies": { | ||
| "@babel/types": "~7.28.2", | ||
| "@endo/compartment-mapper": "^2.0.0", | ||
| "@endo/module-source": "^1.4.0", | ||
| "@endo/test262-runner": "^0.1.49", | ||
| "@endo/compartment-mapper": "^2.1.0", | ||
| "@endo/module-source": "^1.4.1", | ||
| "@endo/test262-runner": "^0.1.50", | ||
| "ava": "catalog:dev", | ||
@@ -118,3 +118,3 @@ "c8": "catalog:dev", | ||
| "tsd": "catalog:dev", | ||
| "typescript": "~5.9.2" | ||
| "typescript": "catalog:dev" | ||
| }, | ||
@@ -149,3 +149,3 @@ "files": [ | ||
| }, | ||
| "gitHead": "f91329e8616a19f131d009356a5f11ef11c839cc" | ||
| "gitHead": "c3616c39c35f2d052f7083aba31054910951beb4" | ||
| } |
+4
-1
@@ -29,3 +29,5 @@ /** | ||
| FinalizationRegistry, | ||
| Float32Array, | ||
| // Renamed to FERAL_* because it enables the NaN side-channel | ||
| Float64Array: FERAL_FLOAT64_ARRAY, | ||
| DataView, | ||
| JSON, | ||
@@ -35,2 +37,3 @@ Map, | ||
| Number, | ||
| BigInt, | ||
| Object, | ||
@@ -37,0 +40,0 @@ Promise, |
+15
-14
@@ -98,17 +98,6 @@ import { toStringTagSymbol, iteratorSymbol } from './commons.js'; | ||
| '%ObjectPrototype%': { | ||
| toString: true, | ||
| ...minEnablements['%ObjectPrototype%'], | ||
| valueOf: true, | ||
| }, | ||
| '%ArrayPrototype%': { | ||
| toString: true, | ||
| push: true, // set by "Google Analytics" | ||
| concat: true, // set by mobx generated code (old TS compiler?) | ||
| [iteratorSymbol]: true, // set by mobx generated code (old TS compiler?) | ||
| }, | ||
| '%IteratorPrototype%': { | ||
| [iteratorSymbol]: true, // is sometimes used in custom iterators and generators implementations eg. @rive-app/canvas | ||
| }, | ||
| // Function.prototype has no 'prototype' property to enable. | ||
@@ -119,14 +108,26 @@ // Function instances have their own 'name' and 'length' properties | ||
| '%FunctionPrototype%': { | ||
| ...minEnablements['%FunctionPrototype%'], | ||
| constructor: true, // set by "regenerator-runtime" | ||
| bind: true, // set by "underscore", "express" | ||
| toString: true, // set by "rollup" | ||
| }, | ||
| '%ErrorPrototype%': { | ||
| ...minEnablements['%ErrorPrototype%'], | ||
| constructor: true, // set by "fast-json-patch", "node-fetch" | ||
| message: true, | ||
| name: true, // set by "precond", "ava", "node-fetch", "node 14" | ||
| toString: true, // set by "bluebird" | ||
| }, | ||
| '%IteratorPrototype%': { | ||
| ...minEnablements['%IteratorPrototype%'], | ||
| [iteratorSymbol]: true, // is sometimes used in custom iterators and generators implementations eg. @rive-app/canvas | ||
| }, | ||
| '%ArrayPrototype%': { | ||
| toString: true, | ||
| push: true, // set by "Google Analytics" | ||
| concat: true, // set by mobx generated code (old TS compiler?) | ||
| [iteratorSymbol]: true, // set by mobx generated code (old TS compiler?) | ||
| }, | ||
| '%TypeErrorPrototype%': { | ||
@@ -133,0 +134,0 @@ constructor: true, // set by "readable-stream" |
| import { | ||
| FERAL_FUNCTION, | ||
| Float32Array, | ||
| FERAL_FLOAT64_ARRAY, | ||
| Map, | ||
@@ -75,3 +75,3 @@ Set, | ||
| const TypedArray = getPrototypeOf(Float32Array); | ||
| const TypedArray = getPrototypeOf(FERAL_FLOAT64_ARRAY); | ||
@@ -78,0 +78,0 @@ // 23.1.5.2 The %MapIteratorPrototype% Object |
+2
-0
@@ -39,2 +39,3 @@ // Copyright (C) 2018 Agoric | ||
| import tameMathObject from './tame-math-object.js'; | ||
| import { tameNaNSideChannel } from './tame-nan-sidechannel.js'; | ||
| import tameRegExpConstructor from './tame-regexp-constructor.js'; | ||
@@ -357,2 +358,3 @@ import enablePropertyOverrides from './enable-property-overrides.js'; | ||
| addIntrinsics(tameMathObject()); | ||
| tameNaNSideChannel(); | ||
| addIntrinsics(tameRegExpConstructor(regExpTaming)); | ||
@@ -359,0 +361,0 @@ addIntrinsics(tameSymbolConstructor()); |
@@ -513,3 +513,3 @@ import { getEnvironmentOption as getenv } from '@endo/env-options'; | ||
| * will always be empty. | ||
| * @param {{errors?: Error[], noAggregateErrors?: boolean}} [options] | ||
| * @param {{errors?: Error[], noAggregateErrors?: boolean | undefined}} [options] | ||
| */ | ||
@@ -556,3 +556,3 @@ const asyncJobQueue = ({ errors = [], noAggregateErrors = false } = {}) => { | ||
| * will always be empty. | ||
| * @param {{errors?: Error[], noAggregateErrors?: boolean}} [options] | ||
| * @param {{errors?: Error[], noAggregateErrors?: boolean | undefined}} [options] | ||
| */ | ||
@@ -630,3 +630,3 @@ const syncJobQueue = ({ errors = [], noAggregateErrors = false } = {}) => { | ||
| * @param {string} moduleSpecifier - The module specifier to load. | ||
| * @param {{ noAggregateErrors?: boolean}} options | ||
| * @param {{ noAggregateErrors?: boolean | undefined}} options | ||
| */ | ||
@@ -682,3 +682,3 @@ export const load = async ( | ||
| * @param {string} moduleSpecifier - The module specifier to load. | ||
| * @param {{ noAggregateErrors?: boolean}} options | ||
| * @param {{ noAggregateErrors?: boolean | undefined}} options | ||
| */ | ||
@@ -685,0 +685,0 @@ |
+13
-4
@@ -62,6 +62,3 @@ /* eslint-disable no-restricted-globals */ | ||
| EvalError: 'EvalError', | ||
| // https://github.com/tc39/proposal-float16array | ||
| Float16Array: 'Float16Array', | ||
| Float32Array: 'Float32Array', | ||
| Float64Array: 'Float64Array', | ||
| Int8Array: 'Int8Array', | ||
@@ -148,2 +145,14 @@ Int16Array: 'Int16Array', | ||
| // We move these from universalPropertyNames because the NaN side channel | ||
| // means that they are not quite harmless. | ||
| // We move them to initialGlobalPropertyNames so that they'll still be | ||
| // included in the primordials, repaired, and hardened. Thus, they | ||
| // can be endowed into compartments without hazard beyond the | ||
| // NaN side channel. | ||
| // | ||
| // // https://github.com/tc39/proposal-float16array | ||
| Float16Array: 'Float16Array', | ||
| Float32Array: 'Float32Array', | ||
| Float64Array: 'Float64Array', | ||
| // ESNext | ||
@@ -150,0 +159,0 @@ |
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 too big to display
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 too big to display
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 too big to display
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
4343481
0.99%85
1.19%98893
1.06%16
-5.88%