-
Notifications
You must be signed in to change notification settings - Fork 46
openai agents shell/apply_patch example #221
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
🦋 Changeset detectedLatest commit: 0144558 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
237045a to
fff782d
Compare
There was a problem hiding this 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-reactdependency 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: anywith 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
allResultsfield from API response - Add error boundary to React app
The core functionality is well-implemented with good UX. Address the critical issues before merging.
commit: |
🐳 Docker Image PublishedFROM cloudflare/sandbox:0.0.0-pr-221-6c52ec2Version: You can use this Docker image with the preview package from this PR. |
There was a problem hiding this 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
- Path traversal vulnerability in
resolve()- doesn't normalize..sequences before validation - Missing OpenAI API key configuration - README mentions it but code never uses it
- Invalid model name
gpt-5.1- not a valid OpenAI model - Extensive use of
anytype - violates repository standards (CLAUDE.md: "Never use theanytype") - Unused dependency
@codesandbox/sandpack-react- adds unnecessary weight
Major Issues
- Commented-out
seedWorkspace()with vague explanation should be removed or fixed - Missing
checkscript in package.json (other examples have this) - Not using centralized error classes from
@repo/shared/errors
Minor Issues
- Hardcoded
DEBUG = truein 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.
examples/openai-agents/src/index.ts
Outdated
| throw new Error(`Operation outside workspace: ${relativePath}`); | ||
| } | ||
| // Normalize path separators | ||
| return resolved.replace(/\/+/g, '/'); |
There was a problem hiding this comment.
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;
}
examples/openai-agents/src/logger.ts
Outdated
| @@ -0,0 +1,41 @@ | |||
| // Global flag to enable/disable logging | |||
| const DEBUG = true; | |||
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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
}| 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
stack trace information
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 26 days ago
To fix this, ensure that error details returned to users are generic and do not include any sensitive or internal details. Instead of sending the raw error message (potentially containing sensitive internal information), always send a fixed, generic error message such as "Internal server error" or "An error occurred". Log the real error and stack on the server for diagnostics, as is already being done. The only necessary change is to remove errorMessage from the HTTP response and replace it with a generic string.
Edit the region where the error response is constructed (lines 142–147). No code elsewhere needs to change. No extra dependencies or imports are required.
-
Copy modified line R143
| @@ -140,7 +140,7 @@ | ||
| }); | ||
| return new Response( | ||
| JSON.stringify({ | ||
| error: errorMessage || 'Internal server error', | ||
| error: 'Internal server error', | ||
| naturalResponse: 'An error occurred while processing your request.', | ||
| commandResults: [], | ||
| fileOperations: [] |
There was a problem hiding this 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. | |||
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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([]);
}There was a problem hiding this comment.
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.
There was a problem hiding this 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.
2baf081 to
29dfb79
Compare
There was a problem hiding this 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/errorsinstead of genericErrorinstances (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
anytypes 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' |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@copilot fix this please
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still shows 'sandbox-do' in the latest commit. This needs to be changed to 'openai-adapter' to reflect where this code actually runs (SDK client layer, not Durable Object).
| logger.error('Cannot update missing file', undefined, { | ||
| path: operation.path | ||
| }); | ||
| throw new Error(`Cannot update missing file: ${operation.path}`); |
There was a problem hiding this comment.
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.
There was a problem hiding this 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:
-
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. -
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. -
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.
There was a problem hiding this 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
anytypes - 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); |
There was a problem hiding this comment.
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);
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs fixing. Without localStorage.removeItem(STORAGE_KEY), corrupted data persists and breaks the app on every reload. The fix is a one-line addition to the catch block.
|
|
||
| # 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 |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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';eda06f8 to
6c4528b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Claude Code Review
High-quality implementation with comprehensive tests and documentation. The core adapters are solid, but need fixes before merge.
Critical Issues (Must Fix)
- Security warning needs prominence - The security implications of auto-approving AI operations should be at the top of documentation, not buried at the bottom
- Invalid model in example -
gpt-5.1doesn't exist, should begpt-4-turbo
Important Issues (Should Fix)
- Add rate limiting to example - Example has no protection against API abuse
- Path resolution edge case - Needs test for absolute paths that start with workspace root
- Missing deployment guidance - Docs should cover Cloudflare-specific considerations (Durable Objects, costs, rate limiting)
Strengths
- No
anytypes, proper TypeScript throughout - Excellent security tests for path traversal
- Comprehensive documentation
- Follows SDK patterns correctly
- Optional peer dependency approach is sound
Verdict: Approve after addressing the 2 critical issues.
See inline comments for specifics.
| - **`Shell`**: Implements the OpenAI Agents `Shell` interface, allowing agents to execute shell commands in the sandbox | ||
| - **`Editor`**: Implements the OpenAI Agents `Editor` interface, enabling agents to create, update, and delete files using patch operations | ||
|
|
||
| Both adapters automatically collect results from operations, making it easy to track what commands were executed and what files were modified during an agent session. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Security warning needs to be prominent at the top.
Add this immediately after the title:
> **⚠️ SECURITY WARNING**
>
> These adapters enable AI agents to execute arbitrary shell commands and modify files. When using `needsApproval: false`, the AI has **unrestricted access** within the container.
>
> **Production deployments MUST:**
> - Implement approval workflows for sensitive operations
> - Set up rate limiting to prevent abuse
> - Monitor and log all agent operations
> - Validate AI responses before executing operationsDevelopers scanning quickly will miss the security implications if it's only in the example README.
| // Create agent with both shell and patch tools, auto-approval for web API | ||
| console.debug('[openai-example]', 'Creating Agent', { | ||
| name: 'Sandbox Studio', | ||
| model: 'gpt-5.1' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Invalid model name.
gpt-5.1 doesn't exist. Change to:
model: 'gpt-4-turbo', // or 'gpt-4'| if (!sessionId) { | ||
| return new Response('Missing X-Session-Id header', { status: 400 }); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important: No rate limiting.
This example should demonstrate production-ready patterns. Add basic rate limiting:
const RATE_LIMIT = 10; // requests per minute
const rateLimitMap = new Map<string, { count: number; resetAt: number }>();
function checkRateLimit(sessionId: string): boolean {
const now = Date.now();
const entry = rateLimitMap.get(sessionId);
if (!entry || now >= entry.resetAt) {
rateLimitMap.set(sessionId, { count: 1, resetAt: now + 60000 });
return true;
}
if (entry.count >= RATE_LIMIT) return false;
entry.count++;
return true;
}
// In fetch:
if (!checkRateLimit(sessionId)) {
return new Response('Rate limit exceeded', { status: 429 });
}| } | ||
| } | ||
|
|
||
| private resolve(relativePath: string): string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important: Path resolution edge case.
What happens if the AI provides an absolute path that's already within the workspace?
Example: With root = '/workspace', if path is /workspace/file.txt:
- Leading
/gets stripped →workspace/file.txt - Joined with root →
/workspace/workspace/file.txt❌
Add test case:
it('should handle absolute paths within workspace', async () => {
const editor = new Editor(mockSandbox, '/workspace');
const operation = {
type: 'create_file',
path: '/workspace/file.txt',
diff: 'content'
};
await editor.createFile(operation);
expect(mockSandbox.writeFile).toHaveBeenCalledWith(
'/workspace/file.txt', // Not /workspace/workspace/file.txt
'content',
{ encoding: 'utf-8' }
);
});|
|
||
| - [OpenAI Agents SDK Documentation](https://github.com/openai/openai-agents-js/) | ||
| - [Session Execution Architecture](./SESSION_EXECUTION.md) - Understanding how commands execute in sandboxes | ||
| - [Example Implementation](../examples/openai-agents/src/index.ts) - Full working example |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important: Missing Cloudflare deployment guidance.
Add section covering:
- Durable Objects and session persistence
- Rate limiting recommendations
- Cost considerations (container + OpenAI API)
- wrangler.jsonc configuration
- Using secrets for API keys
Example structure:
## Deploying to Production
### Cloudflare-Specific Considerations
1. **Durable Objects:** Sessions persist across requests
2. **Rate Limiting:** Use Workers rate limiting or KV
3. **Costs:** Container CPU time + OpenAI tokens + DO requests
4. **Security:** Use Cloudflare Access + audit logs in KV
### Required Configuration
Your `wrangler.jsonc`:
```jsonc
{
"durable_objects": {
"bindings": [
{ "name": "Sandbox", "class_name": "Sandbox" }
]
}
}For production, use secrets:
wrangler secret put OPENAI_API_KEY| outcome.type === 'exit' ? outcome.exitCode : null; | ||
| const timestamp = Date.now(); | ||
| this.results.push({ | ||
| command: String(command), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Redundant string coercion.
command, stdout, and stderr are already strings from the API contract. The String() calls are defensive but unnecessary:
this.results.push({
command, // Already string
stdout, // Already string
stderr, // Already string
exitCode: collectedExitCode,
timestamp
});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.
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.
Updated the Editor's resolve method to correctly handle absolute paths that start with the workspace root, preventing duplication of the root in resolved paths. Added a test to verify correct behavior when creating files with absolute paths within the workspace.
ed1ef79 to
0144558
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Claude Code Review
Path traversal protection is properly fixed - excellent work on the security implementation. The stack-based normalization correctly handles all edge cases.
Three issues from previous reviews still need attention:
-
Logger component name - Still shows
'sandbox-do'on lines 38-39 ofpackages/sandbox/src/openai/index.ts. Should be'openai-adapter'to accurately reflect this runs in SDK client layer, not Durable Object. -
localStorage cleanup - The catch block in
examples/openai-agents/src/app.tsx:77still doesn't clear corrupted data. AddlocalStorage.removeItem(STORAGE_KEY)so the app can recover instead of failing on every reload. -
Duplicate error utilities -
isErrorWithProperties,getErrorMessage,toErrorare duplicated betweenpackages/sandbox/src/openai/index.tsandexamples/openai-agents/src/index.ts. Consider moving to@repo/sharedfor reuse.
The core implementation is solid:
- No
anytypes (adheres to CLAUDE.md standards) - Comprehensive security tests covering path traversal attacks
- Clean adapter pattern with proper result collection
- Good documentation with security warnings
Verdict: Fix the 3 issues above before merge. Quick fixes that improve debuggability and maintainability.
| import type { Sandbox } from '../sandbox'; | ||
|
|
||
| const logger: Logger = createLogger({ | ||
| component: 'sandbox-do', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change component name from 'sandbox-do' to 'openai-adapter'. This code runs in the SDK client layer, not the Durable Object, so the current name makes debugging confusing.
| const parsed = JSON.parse(saved); | ||
| setMessages(parsed); | ||
| } catch (error) { | ||
| console.error('Error loading history:', error); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add localStorage.removeItem(STORAGE_KEY); in the catch block. When JSON.parse fails, corrupted data stays in localStorage and breaks the app on every reload.
| }); | ||
|
|
||
| // Helper functions for error handling | ||
| function isErrorWithProperties(error: unknown): error is { |
There was a problem hiding this comment.
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). Consider moving to @repo/shared for reuse across the monorepo.
Uh oh!
There was an error while loading. Please reload this page.