S11.3: new Function() / eval() Escape aus Page-Sandbox verhindern #64

Closed
opened 2026-06-18 15:53:15 +00:00 by Artur · 1 comment
Owner

Problembeschreibung

Page-Scripts können via new Function() oder indirektem eval() die Sandbox verlassen, weil diese Konstrukte im globalen Bun-Scope ausgeführt werden:

// Im Page-Script (innerhalb von eval() im with(_win)):
new Function('return typeof process')()  // → "object" — escapet!
(0, eval)('typeof process')              // → "object" — escapet!

Ursache: new Function() erzeugt einen FRESH globalen Scope, der NICHT im with(_win) liegt. (0, eval)() ist indirect eval, das im globalen Scope läuft.

Lösungsansatz

Option A (Proxy-patch): Function.prototype patchen, sodass new Function(code) automatisch in unserem Realm ausgeführt wird.

Option B (eval-patch): Indirektes eval abfangen.

Option C (security-by-depth): Zusätzliche Node-Blocker in den new Function-Parametern — aber new Function hat keinen Zugriff auf lokale vars. Die einzige Möglichkeit ist, die globalen Referenzen zu blocken.

Option D (require/import blocken): var require = void 0; und var import = void 0; im with(_win). Das verhindert Zugriff auf Node-Module aber nicht auf globale Werte.

Entscheidung: Mehrschichtiger Ansatz:

  1. Node-Blocker per var (S11.2)
  2. require/import blocken in diesem Issue
  3. Function.prototype patchen als optionale Hardening-Schicht

Akzeptanzkriterien

  • new Function('return typeof Bun')()"undefined"
  • (0, eval)('typeof process')"undefined" oder Sicherheitsfehler
  • typeof require"undefined" im Page-Script
  • Bestehende React-48-Tests bleiben grün

Betroffene Dateien

Datei Änderung
src/js/execution-realm.ts var require = void 0; var import = void 0;
src/js/execution-realm.ts Function.prototype Patch (optional)
tests/unit/sprint11-sandbox-escape.test.ts Neuer Test

Risiken

  • Function.prototype Patch könnte Webpack/CRA Builds brechen die new Function nutzen
  • import blocken könnte dynamic import() in Modulen brechen

Testplan

  • Unit-Test: Sandbox-Escape Szenarien
  • Integration: React 48er Suite, jQuery, Angular
## Problembeschreibung Page-Scripts können via `new Function()` oder indirektem `eval()` die Sandbox verlassen, weil diese Konstrukte im globalen Bun-Scope ausgeführt werden: ```javascript // Im Page-Script (innerhalb von eval() im with(_win)): new Function('return typeof process')() // → "object" — escapet! (0, eval)('typeof process') // → "object" — escapet! ``` **Ursache:** `new Function()` erzeugt einen FRESH globalen Scope, der NICHT im `with(_win)` liegt. `(0, eval)()` ist indirect eval, das im globalen Scope läuft. ## Lösungsansatz **Option A (Proxy-patch):** `Function.prototype` patchen, sodass `new Function(code)` automatisch in unserem Realm ausgeführt wird. **Option B (eval-patch):** Indirektes eval abfangen. **Option C (security-by-depth):** Zusätzliche Node-Blocker in den `new Function`-Parametern — aber `new Function` hat keinen Zugriff auf lokale vars. Die einzige Möglichkeit ist, die globalen Referenzen zu blocken. **Option D (require/import blocken):** `var require = void 0;` und `var import = void 0;` im `with(_win)`. Das verhindert Zugriff auf Node-Module aber nicht auf globale Werte. **Entscheidung:** Mehrschichtiger Ansatz: 1. Node-Blocker per `var` (S11.2) 2. `require`/`import` blocken in diesem Issue 3. `Function.prototype` patchen als optionale Hardening-Schicht ## Akzeptanzkriterien - [ ] `new Function('return typeof Bun')()` → `"undefined"` - [ ] `(0, eval)('typeof process')` → `"undefined"` oder Sicherheitsfehler - [ ] `typeof require` → `"undefined"` im Page-Script - [ ] Bestehende React-48-Tests bleiben grün ## Betroffene Dateien | Datei | Änderung | |-------|----------| | `src/js/execution-realm.ts` | `var require = void 0; var import = void 0;` | | `src/js/execution-realm.ts` | `Function.prototype` Patch (optional) | | `tests/unit/sprint11-sandbox-escape.test.ts` | Neuer Test | ## Risiken - `Function.prototype` Patch könnte Webpack/CRA Builds brechen die `new Function` nutzen - `import` blocken könnte dynamic `import()` in Modulen brechen ## Testplan - Unit-Test: Sandbox-Escape Szenarien - Integration: React 48er Suite, jQuery, Angular
Author
Owner

Sprint 14 — Fix implementiert

Commit: dc0c24b
24 Tests — 0 Regression

Die new Function() Escape-Lücke ist geschlossen:

  • new Function("return typeof Bun")()undefined (vorher: "object")
  • window.Function, globalThis.Function ebenfalls gesandboxt
  • this === window in new Function() korrigiert
  • Nested new Function() korrekt gekapselt

Verbleibend: (0, eval)("typeof Bun") — Indirect eval. Das ist per JS-Spec nicht abfangbar (eval wird im globalen Scope ausgeführt). Wird als separates Issue dokumentiert.

## Sprint 14 — Fix implementiert ✅ **Commit:** `dc0c24b` **24 Tests — 0 Regression** Die `new Function()` Escape-Lücke ist geschlossen: - `new Function("return typeof Bun")()` → `undefined` (vorher: `"object"`) - `window.Function`, `globalThis.Function` ebenfalls gesandboxt - `this === window` in new Function() korrigiert - Nested `new Function()` korrekt gekapselt **Verbleibend:** `(0, eval)("typeof Bun")` — Indirect eval. Das ist per JS-Spec **nicht abfangbar** (eval wird im globalen Scope ausgeführt). Wird als separates Issue dokumentiert.
Artur closed this issue 2026-06-18 16:44:53 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
glow-all/true-headless-browser#64
No description provided.