|
78 | 78 | thisGlobalPrototypes['AsyncGeneratorFunction'] = eval('(async function*() {})').constructor.prototype; |
79 | 79 | } catch (e) {} |
80 | 80 |
|
| 81 | +// Cache this-realm dangerous function constructors. |
| 82 | +// Used to block raw host Function constructors from leaking when handler |
| 83 | +// methods are called directly (e.g., via showProxy handler exposure). |
| 84 | +// This complements isDangerousFunctionConstructor which checks OTHER-realm constructors. |
| 85 | +let thisAsyncFunctionCtor; |
| 86 | +let thisGeneratorFunctionCtor; |
| 87 | +let thisAsyncGeneratorFunctionCtor; |
| 88 | +try { |
| 89 | + if (thisGlobalPrototypes.AsyncFunction) { |
| 90 | + const desc = thisReflectGetOwnPropertyDescriptor(thisGlobalPrototypes.AsyncFunction, 'constructor'); |
| 91 | + if (desc) thisAsyncFunctionCtor = desc.value; |
| 92 | + } |
| 93 | +} catch (e) {} |
| 94 | +try { |
| 95 | + if (thisGlobalPrototypes.GeneratorFunction) { |
| 96 | + const desc = thisReflectGetOwnPropertyDescriptor(thisGlobalPrototypes.GeneratorFunction, 'constructor'); |
| 97 | + if (desc) thisGeneratorFunctionCtor = desc.value; |
| 98 | + } |
| 99 | +} catch (e) {} |
| 100 | +try { |
| 101 | + if (thisGlobalPrototypes.AsyncGeneratorFunction) { |
| 102 | + const desc = thisReflectGetOwnPropertyDescriptor(thisGlobalPrototypes.AsyncGeneratorFunction, 'constructor'); |
| 103 | + if (desc) thisAsyncGeneratorFunctionCtor = desc.value; |
| 104 | + } |
| 105 | +} catch (e) {} |
| 106 | + |
| 107 | +function isThisDangerousFunctionConstructor(value) { |
| 108 | + return value === thisFunction || |
| 109 | + (thisAsyncFunctionCtor && value === thisAsyncFunctionCtor) || |
| 110 | + (thisGeneratorFunctionCtor && value === thisGeneratorFunctionCtor) || |
| 111 | + (thisAsyncGeneratorFunctionCtor && value === thisAsyncGeneratorFunctionCtor); |
| 112 | +} |
| 113 | + |
81 | 114 | const { |
82 | 115 | getPrototypeOf: thisReflectGetPrototypeOf, |
83 | 116 | setPrototypeOf: thisReflectSetPrototypeOf, |
@@ -566,7 +599,15 @@ function createBridge(otherInit, registerProxy) { |
566 | 599 | return thisDefaultGet(this, object, key, desc); |
567 | 600 | } |
568 | 601 | const proto = thisReflectGetPrototypeOf(target); |
569 | | - return proto === null ? undefined : proto.constructor; |
| 602 | + if (proto === null) return undefined; |
| 603 | + const ctor = proto.constructor; |
| 604 | + // Defense in depth: block this-realm dangerous function constructors. |
| 605 | + // Normally handler methods are only called by the proxy mechanism |
| 606 | + // which handles return values safely, but if the handler is exposed |
| 607 | + // (e.g., via util.inspect showProxy), attackers can call get() |
| 608 | + // directly with a forged target, leaking raw host constructors. |
| 609 | + if (isThisDangerousFunctionConstructor(ctor)) return {}; |
| 610 | + return ctor; |
570 | 611 | } |
571 | 612 | case '__proto__': { |
572 | 613 | const desc = otherSafeGetOwnPropertyDescriptor(object, key); |
|
0 commit comments