Skip to content

feat: implement security hardening measures against stack overflow escape attacks#47

Merged
frontegg-david merged 6 commits intorelease/2.10.xfrom
security-fix
Feb 2, 2026
Merged

feat: implement security hardening measures against stack overflow escape attacks#47
frontegg-david merged 6 commits intorelease/2.10.xfrom
security-fix

Conversation

@frontegg-david
Copy link
Contributor

@frontegg-david frontegg-david commented Feb 2, 2026

Summary by CodeRabbit

  • Bug Fixes

    • Improved detection and blocking of advanced computed/coercion patterns that could enable sandbox escapes.
    • Hardened prototype and error-constructor protections and added runtime verifications to ensure VM integrity.
  • Tests

    • Added extensive security test suites covering promise/constructor/symbol, proxy, stack/overflow, import/bigint, cause/callee, and other escape vectors.
  • Chores

    • Revamped CI test matrix and result aggregation for per-job reporting and artifacts.

@coderabbitai
Copy link

coderabbitai bot commented Feb 2, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

This PR enhances sandbox security through three mechanisms: (1) extending ResourceExhaustionRule with detection for computed property access via coercion patterns, (2) adding three comprehensive test suites covering advanced sandbox escape vectors and prototype-chain attacks, and (3) implementing Phase 2 security hardening in the double-VM bootstrap with shadow-proto protections and runtime verification.

Changes

Cohort / File(s) Summary
ResourceExhaustionRule Enhancement
libs/ast/src/rules/resource-exhaustion.rule.ts
Added isSuspiciousCoercionCall() private helper method to detect dangerous coercion patterns (e.g., String(['constructor']), String.fromCharCode(), array coercion) in computed property access paths. Expands detection coverage for sandbox-escape vectors via CallExpression coercion.
Advanced Sandbox Escape Test Suite
libs/core/src/__tests__/enclave.advanced-escape.spec.ts
New comprehensive test suite covering 12+ attack categories (ATK-PROMISE, ATK-INSPECT, ATK-EXCEPT, ATK-PROXY, ATK-STACK, ATK-CTOR, ATK-SYMBOL, ATK-IMPORT, ATK-BIGINT, ATK-CAUSE, ATK-CALLEE, ATK-HOST-SENTINEL) with 100+ test cases validating sandbox isolation against promise manipulation, custom inspect hooks, exception chains, proxies, stack traces, function constructors, and dynamic imports.
Attack Matrix Prototype Chain Tests
libs/core/src/__tests__/enclave.attack-matrix.spec.ts
Added "Stack Overflow Prototype Chain Escape" (ATK-SOE) section with test cases validating sandbox protection against prototype-pollution and constructor-access escape attempts. Includes sentinel-based host-execution prevention tests and prototype-traversal variant coverage (__proto__, constructor chains, Error types).
Stack Overflow CVE-2023-29017 Tests
libs/core/src/__tests__/enclave.stack-overflow-escape.spec.ts
New dedicated test suite (ATK-SOE-01 through ATK-SOE-18) for prototype-chain escape inspired by CVE-2023-29017. Validates sandbox isolation through stack overflow, multi-phase prototype traversal attempts, error constructor chains, and cross-enclave isolation, with verification that host prototypes remain frozen and untouched.
Double-VM Security Hardening
libs/core/src/double-vm/parent-vm-bootstrap.ts
Implemented Phase 2 security hardening: added shadow-proto protections for error prototypes, blocked legacy prototype manipulation methods (__lookupGetter__, __defineGetter__, etc.), froze additional error types (URIError, EvalError), wrapped Error constructors, and added runtime verification before user-code execution to ensure prototypes remain frozen in both parent and inner VM realms.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Sandboxes now have layers deep,
Prototypes frozen, secrets to keep,
Coercions caught, escapes denied,
Stack overflows neutralized with pride,
From CVE's wounds, we've learned to defend!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main objective: implementing security hardening against stack overflow escape attacks. The changes across multiple files focus on this core goal, including detection enhancements, comprehensive test coverage, and VM bootstrap hardening.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch security-fix

Comment @coderabbitai help to get the list of available commands and usage tips.

@frontegg-david frontegg-david changed the base branch from main to release/2.10.x February 2, 2026 14:33
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@libs/core/src/double-vm/parent-vm-bootstrap.ts`:
- Around line 1688-1725: The wrapper created by wrapErrorCtor replaces global
constructors (WrappedCtor) but only copies prototype properties, which drops
static properties like Error.prepareStackTrace and Error.stackTraceLimit; to
fix, after defining WrappedCtor in wrapErrorCtor call
Object.setPrototypeOf(WrappedCtor, OrigCtor) so WrappedCtor inherits static
properties from OrigCtor (do this before attempting to freeze WrappedCtor), and
ensure this change is applied for all wrapped constructors (Error, TypeError,
RangeError, SyntaxError, ReferenceError, EvalError, URIError).
🧹 Nitpick comments (3)
libs/ast/src/rules/resource-exhaustion.rule.ts (1)

332-341: Limit array‑coercion detection to actual coercion methods

This currently flags any ['constructor'].<method>() call, which is broader than the documented toString/join coercion patterns and can over‑block safe code. Consider checking the method name before flagging.

♻️ Proposed refinement
-    if (node.callee.type === 'MemberExpression' && node.callee.object.type === 'ArrayExpression') {
+    if (
+      node.callee.type === 'MemberExpression' &&
+      node.callee.object.type === 'ArrayExpression' &&
+      node.callee.property.type === 'Identifier' &&
+      (node.callee.property.name === 'toString' || node.callee.property.name === 'join')
+    ) {
       const arr = node.callee.object;
       if (arr.elements.length === 1 && arr.elements[0]?.type === 'Literal') {
         const value = String(arr.elements[0].value).toLowerCase();
         if (dangerousStrings.includes(value)) {
           return true;
         }
       }
     }
libs/core/src/__tests__/enclave.attack-matrix.spec.ts (1)

1353-1472: Ensure Enclave disposal even when assertions fail

If an assertion throws before the tail dispose(), the VM can leak into subsequent tests. A try/finally (or shared helper) keeps cleanup deterministic.

♻️ Example pattern
-      const result = await enclave.run<{
-        attempts: Array<{ name: string; result?: string; error?: string; blocked?: boolean }>;
-        totalAttempts: number;
-      }>(code);
-
-      // CRITICAL ASSERTION: Host code must NEVER have executed
-      expect(hostCodeExecuted).toBe(false);
-      ...
-      enclave.dispose();
+      let result;
+      try {
+        result = await enclave.run<{
+          attempts: Array<{ name: string; result?: string; error?: string; blocked?: boolean }>;
+          totalAttempts: number;
+        }>(code);
+
+        // CRITICAL ASSERTION: Host code must NEVER have executed
+        expect(hostCodeExecuted).toBe(false);
+        ...
+      } finally {
+        enclave.dispose();
+      }
libs/core/src/double-vm/parent-vm-bootstrap.ts (1)

1-12: Add required PR metadata for sandbox/VM security changes

Please ensure the PR description includes the problem/solution summary, test evidence (e.g., yarn test or nx test <project>), and explicit security‑impact notes. Based on learnings PRs must include problem/solution description, test evidence (yarn test or nx test <project>), and security-impact notes for sandbox/VM changes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.github/workflows/push.yml:
- Around line 130-133: The test step (id: test) currently runs matrix.command
piped to tee which masks failures; modify the run invocation to execute under
bash with pipefail enabled (e.g., use "bash -o pipefail -c" or set "set -o
pipefail") so that a failing matrix.command propagates its non-zero exit through
tee and correctly sets steps.test.outcome, and update how matrix.command is
built so it conditionally includes the --coverage flag when matrix.coverage is
true (append --coverage to the command string or construct the final command in
the run step using an if/conditional on matrix.coverage) while still writing
output to test-output.txt via tee.

In `@libs/ast/src/rules/resource-exhaustion.rule.ts`:
- Around line 321-329: The current check in resource-exhaustion.rule.ts that
detects String.fromCharCode only handles dot notation (node.callee.property.type
=== 'Identifier') and misses bracket notation like String['fromCharCode'];
update the conditional in the node.callee check to accept both Identifier
properties with name 'fromCharCode' and Literal/string-literal properties whose
value is 'fromCharCode' (i.e., allow property.type === 'Identifier' &&
property.name === 'fromCharCode' OR property.type === 'Literal'/'StringLiteral'
&& property.value === 'fromCharCode') so both String.fromCharCode(...) and
String['fromCharCode'](...) are flagged.
🧹 Nitpick comments (1)
libs/core/src/__tests__/enclave.advanced-escape.spec.ts (1)

447-495: Missing explicit sentinel assertion.

The test injects a sentinel function to detect host code execution via console.log, but the assertion at line 492 only verifies the result is defined. Consider adding an explicit assertion that hostCodeExecuted remains false to match the pattern used in other sentinel tests (e.g., ATK-HOST-SENTINEL-01 at line 1769).

💡 Proposed fix to add explicit sentinel assertion
       const result = await enclave.run(code);
 
       // The key assertion: host sentinel should not have been called
       // (unless explicitly through the allowed globals path)
+      expect(hostCodeExecuted).toBe(false);
       expect(result).toBeDefined();
 
       enclave.dispose();

@frontegg-david frontegg-david merged commit 2fcf5da into release/2.10.x Feb 2, 2026
4 checks passed
@frontegg-david frontegg-david deleted the security-fix branch February 2, 2026 16:57
github-actions bot added a commit that referenced this pull request Feb 2, 2026
…k overflow escape attacks

Cherry-picked from #47 (merged to release/2.10.x)
Original commit: 2fcf5da

Co-Authored-By: frontegg-david <69419539+frontegg-david@users.noreply.github.com>
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2026

Cherry-pick Created

A cherry-pick PR to main has been automatically created.

Please review and merge if this change should also be in main.

If the cherry-pick is not needed, close the PR.

frontegg-david added a commit that referenced this pull request Feb 2, 2026
…k overflow escape attacks (#48)

Cherry-picked from #47 (merged to release/2.10.x)
Original commit: 2fcf5da

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: frontegg-david <69419539+frontegg-david@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant