Skip to content

Conversation

@threepointone
Copy link
Collaborator

@threepointone threepointone commented Nov 15, 2025

image

@changeset-bot
Copy link

changeset-bot bot commented Nov 15, 2025

🦋 Changeset detected

Latest commit: eda06f8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cloudflare/sandbox Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

Solid OpenAI Agents integration example. The SandboxShell and WorkspaceEditor implementations correctly bridge the two SDKs. However, several issues need attention:

Critical:

  • Unused @codesandbox/sandpack-react dependency bloats the package
  • Auto-approval of shell commands and file operations needs prominent security warnings
  • Path traversal protection should use proper path normalization

Important:

  • Replace error: any with proper error types per CLAUDE.md standards
  • Investigate or remove commented seedWorkspace() call
  • README needs security warnings and deployment guidance

Nice to have:

  • Deduplicate CommandResult/FileOperationResult types between frontend/backend
  • Remove unused allResults field from API response
  • Add error boundary to React app

The core functionality is well-implemented with good UX. Address the critical issues before merging.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 16, 2025

Open in StackBlitz

npm i https://pkg.pr.new/cloudflare/sandbox-sdk/@cloudflare/sandbox@221

commit: eda06f8

@github-actions
Copy link
Contributor

github-actions bot commented Nov 16, 2025

🐳 Docker Image Published

FROM cloudflare/sandbox:0.0.0-pr-221-a817d06

Version: 0.0.0-pr-221-a817d06

You can use this Docker image with the preview package from this PR.

@threepointone threepointone changed the title openai agents shell example openai agents shell/apply_patch example Nov 16, 2025
Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This PR adds a well-structured example demonstrating OpenAI agents integration with the Sandbox SDK. The adapter pattern for Shell and Editor interfaces is sound, and the frontend provides good UX. However, there are critical security and correctness issues that must be fixed before merge.

Critical Issues

  1. Path traversal vulnerability in resolve() - doesn't normalize .. sequences before validation
  2. Missing OpenAI API key configuration - README mentions it but code never uses it
  3. Invalid model name gpt-5.1 - not a valid OpenAI model
  4. Extensive use of any type - violates repository standards (CLAUDE.md: "Never use the any type")
  5. Unused dependency @codesandbox/sandpack-react - adds unnecessary weight

Major Issues

  • Commented-out seedWorkspace() with vague explanation should be removed or fixed
  • Missing check script in package.json (other examples have this)
  • Not using centralized error classes from @repo/shared/errors

Minor Issues

  • Hardcoded DEBUG = true in logger
  • Type duplication between frontend/backend
  • Emoji usage violates coding standards
  • localStorage parsing without error boundary

Verdict: Needs fixes before merge. The architecture is solid once security and type safety issues are addressed.

See inline comments for specific fixes.

throw new Error(`Operation outside workspace: ${relativePath}`);
}
// Normalize path separators
return resolved.replace(/\/+/g, '/');
Copy link
Contributor

Choose a reason for hiding this comment

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

CRITICAL: Path traversal vulnerability

This resolve() function doesn't normalize .. sequences before checking if path is within workspace. An attacker could use paths like foo/../../../etc/passwd which would pass the startsWith('/workspace') check but resolve outside the workspace.

Fix: Normalize the path before validation:

private resolve(relativePath: string): string {
  const normalized = relativePath.replace(/^\.?\//, '');
  const resolved = normalized ? `${this.root}/${normalized}` : this.root;
  
  // Normalize to resolve .. sequences
  const parts = resolved.split('/').filter(p => p !== '');
  const stack: string[] = [];
  for (const part of parts) {
    if (part === '..') {
      stack.pop();
    } else if (part !== '.') {
      stack.push(part);
    }
  }
  const finalPath = '/' + stack.join('/');
  
  if (!finalPath.startsWith(this.root)) {
    throw new Error(`Operation outside workspace: ${relativePath}`);
  }
  return finalPath;
}

@@ -0,0 +1,41 @@
// Global flag to enable/disable logging
const DEBUG = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: Hardcoded debug flag

Debug logging is always enabled in production. Consider using environment variable or the centralized logger from @repo/shared which supports SANDBOX_LOG_LEVEL.

const saved = localStorage.getItem(STORAGE_KEY);
if (saved) {
try {
const parsed = JSON.parse(saved);
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: localStorage parse error crashes app

If localStorage becomes corrupted, JSON.parse fails and user loses access to app. Add error recovery:

try {
  const parsed = JSON.parse(saved);
  setMessages(parsed);
} catch (error) {
  console.error('Error loading history:', error);
  localStorage.removeItem(STORAGE_KEY); // Clear corrupted data
}

Comment on lines +483 to +143
JSON.stringify({
error: errorMessage || 'Internal server error',
naturalResponse: 'An error occurred while processing your request.',
commandResults: [],
fileOperations: []
}),

Check warning

Code scanning / CodeQL

Information exposure through a stack trace Medium

This information exposed to the user depends on
stack trace information
.

Copilot Autofix

AI 1 day ago

To eliminate the possibility of exposing sensitive stack trace or other internal error information to the end user, only return a generic error message in HTTP responses. All specific information about the error (message and stack) should be logged server-side (which the code already does via console.error). To fix the issue, modify the handler to always send a fixed, generic error string (e.g., "Internal server error") in the JSON response's error field, regardless of the error.

Edit lines within the catch block of the handleRunRequest function (examples/openai-agents/src/index.ts, lines 130–151):

  • Do NOT set the recipient error message to getErrorMessage(error) (i.e., no expose the variable errorMessage).
  • Instead, use a fixed error string (e.g., "Internal server error") for what is sent to the user.
  • Optionally, keep the server-side log unchanged: keep error message and stack for debugging.
  • Make sure no direct or indirect exposure of error details goes to the response.

No new methods or imports are required since the console-based logging is sufficient.

Suggested changeset 1
examples/openai-agents/src/index.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/examples/openai-agents/src/index.ts b/examples/openai-agents/src/index.ts
--- a/examples/openai-agents/src/index.ts
+++ b/examples/openai-agents/src/index.ts
@@ -130,13 +130,14 @@
   } catch (error: unknown) {
     const errorMessage = getErrorMessage(error);
     const errorStack = getErrorStack(error);
+    // log full details server-side, but don't expose them to the client
     console.error('[openai-example]', 'Error handling run request', {
       error: errorMessage,
       stack: errorStack
     });
     return new Response(
       JSON.stringify({
-        error: errorMessage || 'Internal server error',
+        error: 'Internal server error',
         naturalResponse: 'An error occurred while processing your request.',
         commandResults: [],
         fileOperations: []
EOF
@@ -130,13 +130,14 @@
} catch (error: unknown) {
const errorMessage = getErrorMessage(error);
const errorStack = getErrorStack(error);
// log full details server-side, but don't expose them to the client
console.error('[openai-example]', 'Error handling run request', {
error: errorMessage,
stack: errorStack
});
return new Response(
JSON.stringify({
error: errorMessage || 'Internal server error',
error: 'Internal server error',
naturalResponse: 'An error occurred while processing your request.',
commandResults: [],
fileOperations: []
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

The path traversal vulnerability is still present and must be fixed. The resolve() function doesn't normalize .. sequences before validation, allowing paths like foo/../../../etc/passwd to pass the startsWith check but resolve outside /workspace when executed by the filesystem.

The README still lacks security warnings about auto-approved operations. This needs prominent documentation before anyone deploys this.

Most other issues from the previous review remain unaddressed (debug logging, localStorage recovery, emojis). These are less critical but should be cleaned up.

Verdict: Needs fixes before merge. Path traversal is the blocker.


Critical issues (must fix):

  • Path traversal vulnerability in resolve() function
  • Missing security warnings in README

Important issues (should fix):

  • Hardcoded debug logging
  • localStorage error recovery

Minor issues (nice to have):

  • Remove emojis per coding standards
  • Add input validation/rate limiting
  • Only log stack traces in development

@@ -0,0 +1,32 @@
# OpenAI Agents with Cloudflare Sandbox

A conversational AI assistant that executes shell commands and edits files in a Cloudflare Sandbox.
Copy link
Contributor

Choose a reason for hiding this comment

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

README needs prominent security warning before anyone deploys this. The auto-approval of all AI operations is a significant risk.

Suggest adding:

## Security Warning

**This example auto-approves all AI operations without human review.** The AI can:
- Execute ANY shell command
- Create, modify, or delete ANY file in /workspace
- No safety limits beyond the container itself

**Do not use in production without proper approval flows and rate limiting.**

const parsed = JSON.parse(saved);
setMessages(parsed);
} catch (error) {
console.error('Error loading history:', error);
Copy link
Contributor

Choose a reason for hiding this comment

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

If localStorage is corrupted, JSON.parse fails but the bad data isn't cleared. Add recovery:

} catch (error) {
  console.error('Error loading history:', error);
  localStorage.removeItem(STORAGE_KEY);
  setMessages([]);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Still needs fixing - add localStorage.removeItem(STORAGE_KEY) in the catch block to clear corrupted data.

Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

The OpenAI Agents integration is well-architected and follows SDK patterns correctly. However, there's a critical path traversal vulnerability that must be fixed before merge.

Critical Issues

Path traversal vulnerability remains unresolved. The resolve() method in Editor class (packages/sandbox/src/openai/index.ts:405-415) doesn't normalize .. sequences before validation. Paths like foo/../../../etc/passwd will pass the startsWith('/workspace') check but escape to parent directories when the filesystem resolves them.

This needs proper normalization that processes .. segments before checking containment. The current implementation only strips leading slashes and checks the literal string, which is insufficient.

README security warnings are missing. The example uses needsApproval: false which auto-approves all AI operations (arbitrary shell commands, file modifications) without any security warnings. Developers copying this for production will create serious vulnerabilities. Need prominent warnings about authentication, rate limiting, command whitelisting, and approval workflows before deployment.

Other Issues

Hardcoded debug logging (examples/openai-agents/src/logger.ts:2): DEBUG = true is always on, even in production. Use environment variable or the centralized logger from @repo/shared.

localStorage recovery (examples/openai-agents/src/app.tsx:57-60): Corrupted data isn't cleared, leaving app in broken state.

Stack trace exposure (flagged by GitHub Security): While logging internally is fine, add comments clarifying stack traces should never be exposed to clients.

What's Good

✓ No any types - excellent type safety
✓ Proper use of centralized logger in SDK
✓ Good package structure with separate exports
✓ Solid foundation for OpenAI integration
✓ Changeset properly created

Verdict

Needs fixes before merge - the path traversal vulnerability is a security blocker. After fixing that and adding README warnings, this will be ready to ship.

Introduces file creation, update, and deletion capabilities via a new WorkspaceEditor and applyPatchTool integration. Adds a logger utility for structured debug/info/error output throughout the backend. Refactors the UI to support persistent chat history, multi-column output, and improved message rendering. Updates dependencies to include Sandpack React for future file editing features. Improves documentation and exposes port 8080 in Dockerfile for local development.
Moved CommandResult and FileOperationResult interfaces to a new types.ts file and updated imports in app.tsx and index.ts. Removed @codesandbox/sandpack-react from dependencies and cleaned up related code. Updated env.d.ts for improved type safety and added a type-check script.
Introduces helper functions for consistent error property extraction and message formatting. Refactors error handling in SandboxShell, WorkspaceEditor, and handleRunRequest to use these helpers, improving reliability and clarity in error logging and reporting.
Introduces Shell and Editor adapters in packages/sandbox/src/openai for integrating OpenAI Agents with Cloudflare Sandbox, including structured command and file operation results. Updates examples/openai-agents to use these adapters, removes local types in favor of shared interfaces, and adds tests for the new adapters. Also updates package.json and tsdown config to export the new openai module and adjusts dependencies.
Reordered import statements for consistency in app.tsx, index.ts, and vite.config.ts. Fixed useEffect dependency array in App component to prevent unnecessary scrolling. Added explicit type to clear history button and improved key usage in list rendering.
Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This PR implements a clean OpenAI Agents integration with good adapter patterns and comprehensive result collection. However, there is one critical security vulnerability that must be fixed before merge.

Critical Issue: Path Traversal Vulnerability

The resolve() method in the Editor class doesn't properly sanitize .. segments before checking path boundaries. This allows directory traversal attacks like ../../etc/passwd to escape the workspace.

Required fix: Normalize path segments and validate containment before filesystem operations. See inline comment for implementation.

Architecture Issues

  • Error handling: Should use centralized error types from @repo/shared/errors instead of generic Error instances (or document why standard errors are required by OpenAI Agents contract)
  • Logger naming: Component should be 'sandbox-client' not 'sandbox-do' since this code runs in the SDK layer
  • Test types: Remove any types in tests, use proper mock interfaces per project standards

Missing Test Coverage

Critical: Add security tests for path traversal attempts (../, ../../, etc.)

Recommended: Add tests for edge cases like non-zero exit codes, stderr output, nested directories, and concurrent operations.

Positive Aspects

  • Clean adapter pattern implementation
  • Excellent structured result collection (CommandResult[], FileOperationResult[])
  • Proper timeout handling
  • Type-safe error guards
  • Correct optional peer dependency pattern
  • Changeset follows project rules

Verdict

Needs fixes before merge - specifically the path traversal vulnerability and security tests. The other issues are important for consistency but not blocking if you want to address them in a follow-up.


const logger: Logger = createLogger({
component: 'sandbox-do',
operation: 'openai-agent'
Copy link
Contributor

Choose a reason for hiding this comment

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

Logger component name should be 'sandbox-client' or 'openai-adapter', not 'sandbox-do'. This code runs in the SDK client layer, not in the Durable Object. Using 'sandbox-do' makes debugging harder since logs incorrectly indicate their source.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@copilot fix this please

Copy link
Contributor

Choose a reason for hiding this comment

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

Still shows 'sandbox-do' on line 38-39. Should be 'openai-adapter' to accurately reflect this runs in the SDK client layer.

logger.error('Cannot update missing file', undefined, {
path: operation.path
});
throw new Error(`Cannot update missing file: ${operation.path}`);
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider using centralized error types from @repo/shared/errors (e.g., ErrorCode.FILE_NOT_FOUND) instead of generic Error instances. This maintains consistency with the SDK's architecture pattern documented in CLAUDE.md.

If the OpenAI Agents contract requires standard Error objects, that's fine - just ensure enough context is included for debugging.

Introduces strict path normalization and validation in the Editor class to prevent file operations outside the workspace via path traversal (e.g., '../'). Extensive tests were added to verify security against various traversal attempts. The README now includes a security warning about auto-approval and risks.
Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

Good progress on addressing previous feedback. The path traversal security is now solid - I traced through multiple attack scenarios and the stack-based normalization correctly handles all edge cases.

Still need fixes for:

  1. Logger component name (line 38-39 of openai/index.ts): Still shows 'sandbox-do' but should be 'openai-adapter'. This makes debugging harder since logs incorrectly indicate their source.

  2. Error stack exposure (lines 132-136 of example worker): getErrorStack() function exists but stack traces shouldn't be in API responses - only server logs. Either remove the function or clarify it's internal-only.

  3. localStorage error recovery (app.tsx line 60): When JSON.parse fails on corrupted data, the bad data isn't cleared. Add localStorage.removeItem(STORAGE_KEY) in the catch block.

The rest looks good - excellent test coverage, proper type safety, and clear security warnings in the README.

Verdict: Fix these three issues before merge.

Copy link
Contributor

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

The localStorage issue from my previous review is still not fixed. The catch block at line 59 needs localStorage.removeItem(STORAGE_KEY) to handle corrupted data.

New issues found:

Critical:

  • Invalid model name 'gpt-5.1' in examples/openai-agents/src/index.ts:78 - this will cause runtime errors. Use 'gpt-4o' or another valid OpenAI model.
  • Hardcoded platform in examples/openai-agents/Dockerfile:9 breaks on non-ARM64 systems

Code quality:

  • Error handling utilities duplicated between packages/sandbox/src/openai/index.ts and examples/openai-agents/src/index.ts - should move to shared package

Positive:

  • Comprehensive security testing for path traversal
  • No any types - proper type safety throughout
  • Excellent documentation with clear security warnings
  • Good architectural patterns

Needs fixes before merge.

const parsed = JSON.parse(saved);
setMessages(parsed);
} catch (error) {
console.error('Error loading history:', error);
Copy link
Contributor

Choose a reason for hiding this comment

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

Still missing localStorage.removeItem(STORAGE_KEY) here. When JSON.parse fails due to corrupted data, the corrupted data remains in localStorage and breaks the app on every reload. Add:

catch (error) {
  console.error('Error loading history:', error);
  localStorage.removeItem(STORAGE_KEY);
}


# On a mac, you might need to actively pick up the
# arm64 build of the image.
FROM --platform=linux/arm64 cloudflare/sandbox-test:0.5.0
Copy link
Contributor

Choose a reason for hiding this comment

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

Hardcoded --platform=linux/arm64 breaks on non-ARM64 systems (Intel Macs, Linux x64). The official images support both platforms, so remove the platform flag:

FROM cloudflare/sandbox-test:0.5.0

});

// Helper functions for error handling
function isErrorWithProperties(error: unknown): error is {
Copy link
Contributor

Choose a reason for hiding this comment

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

These error handling utilities (lines 44-68) are duplicated in examples/openai-agents/src/index.ts (lines 8-31). Move to packages/shared/src/error-utils.ts for reusability:

import { isErrorWithProperties, getErrorMessage, toError } from '@repo/shared';

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