Block handler class reconstruction via util.inspect leak
fix(GHSA-v37h-5mfm-c47c): block handler class reconstruction via util.inspect leak
Block handler class reconstruction via util.inspect leakfd266d-fix-block-handler-class-reconstruction-via-util-cve-2026-24781fixblock handler class reconstruction via util
Committed by patriksimek
commit message
fix(GHSA-v37h-5mfm-c47c): block handler class reconstruction via util.inspect leak
util.inspect({showProxy:true}) leaks a BaseHandler instance to sandbox
code. Prior fixes closed individual method/property leaks on the
instance, but the handler class itself remained reachable via
`Object.getPrototypeOf(handler).constructor` and constructible — letting
attackers build a new handler wrapping an attacker-controlled sandbox
object and use its `.set` trap as a cross-realm read/write channel.
Three-layer defense in lib/bridge.js + lib/setup-sandbox.js:
- Construction token: module-local Symbol captured in createBridge()
closure; all four handler classes require it as first ctor arg.
- getHandlerObject guard: throws VMError if the handler is not registered
in handlerToObject, blocking method calls on forged receivers.
- Constructor sentinel rebind: `.constructor` on every handler prototype
is replaced with a throw-always function so prototype-chain walks from
a leaked handler never reach a callable class.
See test/ghsa/GHSA-v37h-5mfm-c47c/ for repros and invariant tests.Editor assessment
This commit patches CVE-2026-24781. The body is exemplary security prose: it states that util.inspect(showProxy:true) leaks a BaseHandler, that earlier fixes only closed individual leaks, and that the class remained constructible via prototype constructor so its .set trap could carry cross-realm reads and writes. It then lists the three defenses—construction token, getHandlerObject registration guard, and a throw-always constructor sentinel—and points to repros and invariant tests. The single flaw is structural: the advisory ID sits where a scope like bridge or setup-sandbox belongs, and the subject runs long. Content that would otherwise be exemplary is capped by the header.