diff --git a/examples/_data.ts b/examples/_data.ts index 2bcf21b25..1a0f1a924 100644 --- a/examples/_data.ts +++ b/examples/_data.ts @@ -321,82 +321,82 @@ export const sidebar = [ { title: "Spawn a subprocess", href: "/examples/sandbox_spawn_subprocess/", - type: "example", + type: "tutorial", }, { title: "Serve a web framework", href: "/examples/sandbox_web_framework/", - type: "example", + type: "tutorial", }, { title: "Provide SSH access to a sandbox", href: "/examples/sandbox_ssh_access/", - type: "example", + type: "tutorial", }, { title: "Interactive JavaScript REPL", href: "/examples/sandbox_javascript_repl/", - type: "example", + type: "tutorial", }, { title: "Provide a VSCode instance in a sandbox", href: "/examples/sandbox_vscode_instance/", - type: "example", + type: "tutorial", }, { title: "Use template literals with variable interpolation", href: "/examples/sandbox_template_literals/", - type: "example", + type: "tutorial", }, { title: "Error handling", href: "/examples/sandbox_error_handling/", - type: "example", + type: "tutorial", }, { title: "Command cancellation", href: "/examples/sandbox_command_cancellation/", - type: "example", + type: "tutorial", }, { title: "Streaming access string and binary output", href: "/examples/sandbox_access_output/", - type: "example", + type: "tutorial", }, { title: "Set and get environment variables", href: "/examples/sandbox_environment_variables/", - type: "example", + type: "tutorial", }, { title: "Stream output to a local file", href: "/examples/sandbox_stream_output/", - type: "example", + type: "tutorial", }, { title: "Upload files and directories to a sandbox", href: "/examples/sandbox_upload_files/", - type: "example", + type: "tutorial", }, { title: "Control sandbox timeout", href: "/examples/sandbox_timeout_control/", - type: "example", + type: "tutorial", }, { title: "Configure sandbox memory", href: "/examples/sandbox_memory/", - type: "example", + type: "tutorial", }, { title: "Add read-write volumes to your Sandbox", href: "/examples/volumes_tutorial/", - type: "example", + type: "tutorial", }, { title: "Boot instantly with snapshots", href: "/examples/snapshots_tutorial/", - type: "example", + type: "tutorial", }, { title: "Boot a Python environment with snapshots", @@ -408,6 +408,11 @@ export const sidebar = [ href: "/examples/snapshot_python_tutorial/", type: "tutorial", }, + { + title: "Run AI generated code", + href: "/examples/sandbox_for_untrusted_code/", + type: "example", + }, ], }, { diff --git a/examples/sandbox/evaluating_javascript.md b/examples/sandbox/evaluating_javascript.md deleted file mode 100644 index 442239fed..000000000 --- a/examples/sandbox/evaluating_javascript.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Evaluating JavaScript" -description: "Learn how to evaluate JavaScript code in a sandbox." -url: /examples/sandbox_evaluating_javascript/ -layout: sandbox-example.tsx ---- - -You can evaluate JavaScript code in a sandbox using the `eval` function. - -```ts -import { Sandbox } from "@deno/sandbox"; - -await using sandbox = await Sandbox.create(); - -const result = await sandbox.deno.eval(` - const a = 1; - const b = 2; - a + b; -`); -console.log("result:", result); -``` - -Calling `sandbox.deno.eval()` lets you run arbitrary JavaScript snippets -directly inside the sandbox’s Deno runtime without writing files or shelling -out. This is useful when you want to prototype logic, run small computations, or -inspect the sandbox environment itself quickly. Use it for dynamic scripts or -exploratory debugging where creating a full module would be overkill. diff --git a/examples/scripts/sandbox_evaluating_javascript.ts b/examples/scripts/sandbox_evaluating_javascript.ts new file mode 100644 index 000000000..2dafe5aeb --- /dev/null +++ b/examples/scripts/sandbox_evaluating_javascript.ts @@ -0,0 +1,28 @@ +/** + * @title Evaluating JavaScript + * @difficulty beginner + * @tags sandbox + * @run -A + * @resource {https://docs.deno.com/sandbox/} Deno Deploy Sandbox + * @group Deno Deploy + * + * You can evaluate JavaScript code in a sandbox using the `eval` function. + * + * Calling `sandbox.deno.eval()` lets you run arbitrary JavaScript snippets + * directly inside the sandbox’s Deno runtime without writing files or shelling * out. This is useful when you want to prototype logic, run small + * computations, or inspect the sandbox environment itself quickly. Use it for + * dynamic scripts or exploratory debugging where creating a full module would + * be overkill. + */ + +// Import the Deno Sandbox SDK +import { Sandbox } from "jsr:@deno/sandbox"; +// Create a sandbox +await using sandbox = await Sandbox.create(); +// Run JS in the sandbox with eval +const result = await sandbox.deno.eval(` + const a = 1; + const b = 2; + a + b; + `); +console.log("result:", result); diff --git a/examples/scripts/sandbox_for_untrusted_code.ts b/examples/scripts/sandbox_for_untrusted_code.ts new file mode 100644 index 000000000..ac8b36b08 --- /dev/null +++ b/examples/scripts/sandbox_for_untrusted_code.ts @@ -0,0 +1,84 @@ +/** + * @title Spin up a sandbox to run untrusted code + * @difficulty beginner + * @tags sandbox + * @run -A --env-file + * @resource {https://docs.deno.com/sandbox/} Deno Deploy Sandbox + * @group Deno Deploy + * + * Deno Deploy's Sandbox API lets you create secure microVMs to run untrusted code safely. + * In this example, we ask Claude to generate a Deno script that fetches the current Bitcoin price, + * then run that script inside a sandbox with strict resource limits and no access to the host environment. + */ + +// Import the Anthropic SDK and the Deno Sandbox SDK. +import Anthropic from "npm:@anthropic-ai/sdk"; +import { Sandbox } from "jsr:@deno/sandbox"; + +// Create an Anthropic client. +// It automatically picks up ANTHROPIC_API_KEY from your environment. +const client = new Anthropic(); + +// Ask Claude to write some code for us wrapped in a markdown code block. +const response = await client.messages.create({ + model: "claude-opus-4-6", + max_tokens: 1024, + messages: [{ + role: "user", + content: + "Write a Deno script that fetches the current Bitcoin price from the CoinGecko API and prints it.", + }], +}); + +// Take the generated code out of Claude's response. +// Check it's a text block, then strip the markdown +// fences to get the raw source. +const firstBlock = response.content[0]; +if (firstBlock.type !== "text") { + throw new Error(`Unexpected content type: ${firstBlock.type}`); +} +const generatedCode = extractCode(firstBlock.text); + +// Create a sandbox. +await using sandbox = await Sandbox.create(); + +// Write the AI-generated code into the sandbox filesystem. +await sandbox.fs.writeTextFile("/tmp/generated.ts", generatedCode); + +// Run the code inside the sandbox with Deno. +// stdout and stderr are piped so we can capture and display them. +const child = await sandbox.spawn("deno", { + args: [ + "run", + "--allow-net=api.coingecko.com", // Only the specific host we expect + "/tmp/generated.ts", + ], + stdout: "piped", + stderr: "piped", +}); + +// AI-generated code could accidentally (or maliciously) loop forever — +// this ensures we kill the process after 10 seconds no matter what. +const timeout = setTimeout(() => child.kill(), 10_000); + +// Wait for the process to finish and print the results. +// output.stdoutText / stderrText are pre-decoded UTF-8 strings. +// output.status.success is true only if the exit code was 0. +try { + const output = await child.output(); + console.log("Output:\n", output.stdoutText ?? "No output"); + if (!output.status.success) { + console.error("Error:\n", output.stderrText ?? "No error output"); + } +} finally { + clearTimeout(timeout); +} + +// Helper: extract the first code block from a markdown string. +// Falls back to returning the raw text if no fences are found. +function extractCode(text: string): string { + const match = text.match( + /```(?:typescript|ts|javascript|js)?\n([\s\S]*?)```/, + ); + return match ? match[1] : text; +} diff --git a/examples/types.ts b/examples/types.ts index 08f56ea05..90dd42d14 100644 --- a/examples/types.ts +++ b/examples/types.ts @@ -11,6 +11,10 @@ export const TAGS = { title: "web", description: "Works in on the Web", }, + sandbox: { + title: "sandbox", + description: "Uses Deno Deploy Sandbox", + }, }; export const DIFFICULTIES = {