Vercel Sandbox Integration#640
Conversation
- Add @vercel/sandbox dependency and types - Implement `sandbox` tool with support for JS/TS and live previews - Create UI components for streaming logs and iframe previews - Update researcher agent with code execution capabilities - Handle tool result reconstruction in message history Co-authored-by: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
|
|
Warning Review limit reached
More reviews will be available in 5 minutes and 42 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (12)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review Summary by QodoIntegrate Vercel Sandbox for code execution and live previews
WalkthroughsDescription• Integrates Vercel Sandbox for isolated JavaScript/TypeScript code execution • Adds real-time log streaming and live preview capabilities for web servers • Creates UI components for terminal-like log viewer and iframe previews • Updates researcher agent to support code execution and data transformation • Adds sandbox tool configuration and environment variables Diagramflowchart LR
A["Researcher Agent"] -->|uses sandbox tool| B["Sandbox Tool"]
B -->|executes code| C["Vercel Sandbox MicroVM"]
C -->|streams logs| D["SandboxSection Component"]
D -->|displays| E["SandboxLogs"]
C -->|detects server| F["SandboxPreview Component"]
F -->|renders| G["Live Preview iframe"]
File Changes1. lib/schema/sandbox.ts
|
Code Review by Qodo
1. Npm install injection
|
| if (dependencies && dependencies.length > 0) { | ||
| const installCommand = await sandbox.runCommand(`npm install ${dependencies.join(' ')}`) | ||
| for await (const log of installCommand.logs()) { | ||
| const logEntry = { type: log.stream as 'stdout' | 'stderr', content: log.data } | ||
| logs.push(logEntry) | ||
| streamableLogs.update([...logs]) | ||
| } |
There was a problem hiding this comment.
1. Npm install injection 🐞 Bug ⛨ Security
sandboxTool builds an npm install ... command by string-concatenating dependencies, allowing command injection in the microVM (extra commands beyond npm). This breaks the tool’s security boundary and can be used to run arbitrary unintended commands during the install step.
Agent Prompt
### Issue description
`sandboxTool` constructs `npm install` as a single shell string using `dependencies.join(' ')`, which enables command injection if any dependency string includes shell metacharacters.
### Issue Context
The tool parameter schema allows arbitrary strings in `dependencies`, and the tool executes them inside the sandbox via `runCommand`.
### Fix Focus Areas
- Replace string command with structured args (no shell parsing).
- Validate/whitelist dependency names (e.g., npm package name grammar) and reject anything else.
### Fix Focus Areas (code locations)
- lib/agents/tools/sandbox.tsx[37-44]
- lib/schema/sandbox.ts[8-20]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const isServer = /http|express|serve|listen|app\.get|app\.post|createServer/.test(code) | ||
| const cmd = language === 'typescript' ? 'tsx' : 'node' | ||
|
|
||
| const command = await sandbox.runCommand({ | ||
| cmd, | ||
| args: [filename], | ||
| detached: isServer | ||
| }) | ||
|
|
||
| let previewUrl: string | undefined | ||
| if (isServer) { | ||
| previewUrl = await sandbox.domain(3000) | ||
| // Update UI with preview URL | ||
| uiStream.update( | ||
| <SandboxSection | ||
| key={nanoid()} | ||
| logs={streamableLogs.value} | ||
| previewUrl={previewUrl} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| const streamLogs = async () => { | ||
| for await (const log of command.logs()) { | ||
| const logEntry = { type: log.stream as 'stdout' | 'stderr', content: log.data } | ||
| logs.push(logEntry) | ||
| streamableLogs.update([...logs]) | ||
| } | ||
| streamableLogs.done(logs) | ||
| } | ||
|
|
||
| if (isServer) { | ||
| // For servers, stream logs in the background and return immediately | ||
| streamLogs() | ||
| } else { | ||
| // For regular scripts, wait for execution to complete | ||
| await streamLogs() | ||
| const result = await (command as any).wait() | ||
| await sandbox.stop() | ||
| return { | ||
| logs, | ||
| exitCode: result.exitCode, | ||
| type: 'sandbox_result' | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| logs, | ||
| exitCode: 0, | ||
| previewUrl, | ||
| type: 'sandbox_result' | ||
| } |
There was a problem hiding this comment.
2. Sandbox never stopped 🐞 Bug ☼ Reliability
When isServer is true, the tool detaches the process and returns without ever calling sandbox.stop(), leaving microVMs running and consuming resources. The /http|express|.../ heuristic is broad enough to misclassify non-server code, increasing the frequency of this leak.
Agent Prompt
### Issue description
In the server/detached execution path, the sandbox is never stopped, so microVMs can remain alive after the tool returns.
### Issue Context
`sandbox.stop()` is only called in the non-server branch. Server mode is triggered by a regex against the source code, which can produce false positives.
### Fix Focus Areas
- Ensure `sandbox.stop()` is invoked for server runs (e.g., via a `finally` block) or implement a controlled lifecycle/TTL shutdown strategy.
- Avoid heuristic server detection: add an explicit `mode`/`isServer` parameter or detect actual listening port readiness.
- Avoid unhandled background async failures (use `void streamLogs().catch(...)`).
### Fix Focus Areas (code locations)
- lib/agents/tools/sandbox.tsx[46-97]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const isServer = /http|express|serve|listen|app\.get|app\.post|createServer/.test(code) | ||
| const cmd = language === 'typescript' ? 'tsx' : 'node' | ||
|
|
||
| const command = await sandbox.runCommand({ | ||
| cmd, | ||
| args: [filename], | ||
| detached: isServer | ||
| }) |
There was a problem hiding this comment.
3. Typescript runner missing 🐞 Bug ≡ Correctness
TypeScript execution uses cmd = 'tsx' but the tool never installs tsx, so a TypeScript run will fail unless the caller knows to include tsx in dependencies. This makes the advertised TypeScript support unreliable by default.
Agent Prompt
### Issue description
The tool selects `tsx` as the command for TypeScript, but does not guarantee `tsx` exists in the sandbox environment.
### Issue Context
The tool only runs `npm install` when `dependencies` are provided, and it does not add any implicit dependencies based on the selected `language`.
### Fix Focus Areas
- If `language === 'typescript'`, install `tsx` (and typically `typescript`/`@types/node`) automatically before execution.
- Or run through `npx`/a pinned package runner with explicit args.
### Fix Focus Areas (code locations)
- lib/agents/tools/sandbox.tsx[37-53]
- lib/schema/sandbox.ts[8-20]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
This PR integrates Vercel Sandbox into QCX, enabling the AI to execute JavaScript and TypeScript code in isolated microVMs.
Key features:
Infrastructure:
@vercel/sandboxpackage..env.example.app/actions.tsxto handle sandbox tool results in history.PR created automatically by Jules for task 4831652204283404284 started by @ngoiyaeric