Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions examples/tools-example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,34 @@ async function generatorToolExample() {
const _message = await response.getMessage();
}

/**
* Safely evaluate a math expression using ShadowRealm
*
* ShadowRealm provides a secure, isolated JavaScript execution environment
* that prevents access to the host realm's globals (no access to DOM, fetch,
* filesystem, etc.). This makes it safe for evaluating untrusted expressions.
*
* Browser support: Chrome 124+, Edge 124+, Firefox 128+, Safari 18+
* Node.js support: Available behind --experimental-shadow-realm flag (v19+)
* See: https://tc39.es/proposal-shadowrealm/
*/
async function safeEvaluateMath(expression: string): Promise<number> {
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

The function signature declares async and returns Promise<number>, but since ShadowRealm.prototype.evaluate() is synchronous (not a Promise), this function should not be async. Change to:

function safeEvaluateMath(expression: string): number {

This also requires updating the call site at line 236 to remove await.

Copilot uses AI. Check for mistakes.
// ShadowRealm is a TC39 Stage 3 proposal for isolated JavaScript execution
// It creates a separate realm with its own global object, preventing access
// to the host environment's APIs (no DOM, no Node.js APIs, no fetch, etc.)
const realm = new ShadowRealm();
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

TypeScript may not have built-in type definitions for ShadowRealm since it's still a Stage 3 proposal. Consider adding a type declaration at the top of the file to avoid potential TypeScript errors:

// Type declaration for ShadowRealm (TC39 Stage 3 proposal)
declare class ShadowRealm {
  constructor();
  evaluate(sourceText: string): any;
  importValue(specifier: string, bindingName: string): Promise<any>;
}

Copilot uses AI. Check for mistakes.

// The expression is evaluated in complete isolation - even if malicious code
// is injected, it cannot access anything outside the shadow realm
const result = await realm.evaluate(`(${expression})`);
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

The ShadowRealm.prototype.evaluate() method returns synchronously, not a Promise. According to the TC39 spec (https://tc39.es/proposal-shadowrealm/#sec-shadowrealm.prototype.evaluate), this method should not be awaited. Remove the await keyword here.

const result = realm.evaluate(`(${expression})`);
Suggested change
const result = await realm.evaluate(`(${expression})`);
const result = realm.evaluate(`(${expression})`);

Copilot uses AI. Check for mistakes.
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

Wrapping the expression in parentheses allows arbitrary JavaScript expressions, not just math operations. For example, "1, console.log('hi'), 2" would be valid. Consider validating the expression contains only allowed characters (digits, operators, parentheses, whitespace) before evaluation:

// Validate expression contains only safe math characters
if (!/^[\d\s+\-*/.()]+$/.test(expression)) {
  throw new Error('Expression contains invalid characters');
}
const result = realm.evaluate(expression);

Copilot uses AI. Check for mistakes.

if (typeof result !== 'number' || !Number.isFinite(result)) {
throw new Error('Expression did not evaluate to a finite number');
}

return result;
}

/**
* Example 3: Manual Tool Execution
* Define a tool without execute function for manual handling
Expand Down Expand Up @@ -203,10 +231,9 @@ async function manualToolExample() {
}
).expression;

// In a real app, you would safely evaluate this
// For demo purposes only - don't use eval in production!
// Safely evaluate the math expression using ShadowRealm
try {
const _result = eval(expression);
const _result = await safeEvaluateMath(expression);
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

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

Since safeEvaluateMath() should be synchronous (not async), remove the await keyword here:

const _result = safeEvaluateMath(expression);
Suggested change
const _result = await safeEvaluateMath(expression);
const _result = safeEvaluateMath(expression);

Copilot uses AI. Check for mistakes.
} catch (_error) {}
}
}
Expand Down