Skip to content

Commit 1035da6

Browse files
committed
fix: defense-in-depth bridge hardening
Three changes to lib/bridge.js, each independently low-risk and landing as part of the v3.10.6 polish pass: 1. **AggregateError added to errorsList** (resolves GHSA-vwrp-x96c-mhwq doc drift). The result writeup and ATTACKS.md Cat 20 already listed AggregateError as protected, but it wasn't actually in the code's `errorsList`. Adding it makes the docs accurate, extends `protectedHostObjects` coverage to AggregateError.prototype + constructor, and extends `thisAddIdentityMapping` to its prototype. 2. **`nodejs.util.promisify.custom` added to symbol denylist** (defense-in-depth follow-up to GHSA-47x8-96vw-5wg6). Mirrors `nodejs.util.inspect.custom` and `nodejs.rejection`. No live exploit today, but the surface — host machinery invoking a sandbox-defined handler with host-realm arguments — is the same shape, so pre-emptive denial is cheap. 3. **`rebindHandlerConstructor` helper exposed** (closes GHSA-v37h-5mfm-c47c Layer-3 coverage gap). The original sentinel rebind covered the four core handler classes inside bridge.js but not subclasses defined in setup-sandbox.js (BufferHandler).
1 parent d3270cf commit 1035da6

1 file changed

Lines changed: 31 additions & 1 deletion

File tree

lib/bridge.js

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const errorsList = [
4141
'EvalError',
4242
'URIError',
4343
'SuppressedError',
44+
'AggregateError',
4445
'Error',
4546
];
4647

@@ -162,9 +163,21 @@ const thisSymbolToStringTag = Symbol.toStringTag;
162163
const thisSymbolIterator = Symbol.iterator;
163164
const thisSymbolNodeJSUtilInspectCustom = Symbol.for('nodejs.util.inspect.custom');
164165
const thisSymbolNodeJSRejection = Symbol.for('nodejs.rejection');
166+
// SECURITY (post-GHSA-47x8 hardening): defense-in-depth — Node's util.promisify
167+
// uses Symbol.for('nodejs.util.promisify.custom') as a hook. If sandbox code
168+
// could ever provide a host-recognised version of this symbol on an object
169+
// passed to `util.promisify(...)`, Node would invoke the sandbox-defined
170+
// promisifier — likely with host-realm arguments. No live exploit today, but
171+
// the surface mirrors `nodejs.util.inspect.custom` closely enough that
172+
// pre-emptive denial is cheap.
173+
const thisSymbolNodeJSUtilPromisifyCustom = Symbol.for('nodejs.util.promisify.custom');
165174

166175
function isDangerousCrossRealmSymbol(key) {
167-
return key === thisSymbolNodeJSUtilInspectCustom || key === thisSymbolNodeJSRejection;
176+
return (
177+
key === thisSymbolNodeJSUtilInspectCustom ||
178+
key === thisSymbolNodeJSRejection ||
179+
key === thisSymbolNodeJSUtilPromisifyCustom
180+
);
168181
}
169182

170183
/**
@@ -2174,6 +2187,23 @@ function createBridge(otherInit, registerProxy) {
21742187
// token propagates up to BaseHandler.
21752188
return thisReflectConstruct(Subclass, [constructionToken, object]);
21762189
};
2190+
// SECURITY (post-GHSA-v37h hardening): expose the sentinel-rebind helper
2191+
// so that handler subclasses defined in setup-sandbox.js (e.g.
2192+
// BufferHandler) can also have their `.constructor` slot replaced with
2193+
// the throw-always sentinel. Without this, `Object.getPrototypeOf(handler).constructor`
2194+
// on a BufferHandler instance returned the real BufferHandler class (its
2195+
// `prototype.constructor` was the default `writable: true, configurable: true`
2196+
// data property) — Layer 1 (token check) compensated, but Layer 3 was
2197+
// narrower than advertised. This helper closes that gap.
2198+
result.rebindHandlerConstructor = function rebindHandlerConstructor(HandlerClass) {
2199+
thisReflectDefineProperty(HandlerClass.prototype, 'constructor', {
2200+
__proto__: null,
2201+
value: blockedHandlerConstructor,
2202+
writable: false,
2203+
enumerable: false,
2204+
configurable: false,
2205+
});
2206+
};
21772207
// SECURITY (GHSA-v37h-5mfm-c47c): We still expose ReadOnlyHandler as a
21782208
// superclass symbol so that setup-sandbox can declare
21792209
// `class BufferHandler extends ReadOnlyHandler`. The class reference

0 commit comments

Comments
 (0)