DeepSeek Harness: Sandbox and Approval

Last updated: 2026-08-31

An Agent's power lies in its ability to execute operations, but "can execute" doesn't mean "should execute." Approval policies are the Agent's brakes; sandboxes are the Agent's fences. Together, they let the Agent act freely within safe boundaries.

💡 Tip: Approval policies answer "when to ask the user"; sandboxes answer "where to execute." Approval determines decision authority; sandbox determines execution environment boundaries. They are independent but complementary.

📋 Prerequisites: Completed 13-effect.md and 22-capability.md

1. What You'll Learn


Sandbox Approval

2. Approval Policy

(1) Policy Modes

DSH provides four approval modes:

Mode Behavior Best For
always Always allow, no popup Safe operations (read, search)
ask Requires approval, popup confirmation Dangerous operations (create, edit, shell)
ask_with_confirm Double-confirmation popup Extremely dangerous operations (delete, sudo)
deny Auto-deny Operations that must never run (rm -rf /)

(2) ▶ Example 2

YAML
# dsh.config.yaml
approval:
  default: ask

  tools:
    file_edit:
      read: always
      create: ask
      edit: ask
      delete: ask_with_confirm

    shell:
      safe: always
      moderate: ask
      dangerous: ask_with_confirm
      forbidden: deny

    search:
      default: always

    sandbox:
      default: ask

(3) ▶ Example 3

YAML
approval:
  tools:
    file_edit:
      # Path whitelist auto-allow
      auto_allow_paths:
        - /tmp/**
        - /workspace/**
      # Path blacklist auto-deny
      auto_deny_paths:
        - /etc/**
        - /var/**

    shell:
      # Command whitelist
      auto_allow_commands:
        - ls
        - cat
        - grep
        - head
        - wc
        - git status
        - git log
      # Command blacklist
      auto_deny_commands:
        - rm -rf /*
        - mkfs
        - dd if=*

(4) ▶ Example 4

TYPESCRIPT
import { defineTool } from '@deepseek-ai/dsh'

export default defineTool({
  name: 'db_query',
  description: 'Execute SQL query',
  parameters: { /* ... */ },
  approval: {
    level: 'ask',
    rules: [
      { match: { query: /^SELECT/i }, level: 'always' },
      { match: { query: /^DROP/i }, level: 'deny' },
      { match: { query: /^INSERT|^UPDATE|^DELETE/i }, level: 'ask_with_confirm' }
    ]
  },
  async execute({ query }, ctx) {
    return await ctx.database.query(query)
  }
})

3. Permission Presets

(1) Built-in Presets

DSH provides three permission presets:

Preset Description Typical Use
trusted Trust mode, most operations auto-allowed Personal dev environment
standard Standard mode, dangerous operations need approval Default configuration
restricted Restricted mode, strict approval Production environment

(2) Preset Comparison

YAML
# trusted — Trust mode
approval:
  tools:
    file_edit: always
    shell: always
    search: always

# standard — Standard mode
approval:
  tools:
    file_edit:
      read: always
      create: ask
      edit: ask
      delete: ask_with_confirm
    shell: ask

# restricted — Restricted mode
approval:
  tools:
    file_edit: ask_with_confirm
    shell: deny
    search: ask

(3) Choosing a Preset

BASH
# Select preset at startup
pnpm dsh web --preset trusted
pnpm dsh web --preset standard
pnpm dsh web --preset restricted

(4) Custom Presets

YAML
# dsh.config.yaml
approval:
  presets:
    my-team:
      tools:
        file_edit:
          read: always
          create: ask
          edit: ask
          delete: deny
        shell: ask

4. Dangerous Operation Approval Popup

(1) Popup Mechanism

When a tool call requires approval, DSH pauses execution and shows an approval popup:

TEXT 📖 Display only
⚠️ Approval Required: Execute shell command

  Command: npm install bcryptjs
  Working directory: /home/alice/project
  Risk level: MODERATE
  
  [Allow] [Always for npm] [Deny]

(2) Approval Options

Option Description
Allow Allow this operation
Always Allow this type of operation (no more popups)
Always for X Allow operations matching a specific rule
Deny Deny this operation

(3) Batch Approval

Multiple operations can be approved in batch:

TEXT 📖 Display only
⚠️ Batch Approval Required: 3 operations

  1. file_edit: create src/utils.ts
  2. file_edit: edit src/app.ts
  3. shell: npm install bcryptjs

  [Allow All] [Review Each] [Deny All]

(4) Approval Log

All approval decisions are recorded:

TEXT 📖 Display only
[approval] ALLOWED: file_edit(read, src/config.ts) — policy: always
[approval] ASKED: file_edit(create, src/utils.ts) — user: allowed
[approval] DENIED: shell(rm -rf /tmp/test) — policy: deny

5. Sandbox Backend Registration

(1) Sandbox Concept

A sandbox is an isolated environment for tool execution — Agent operations run inside the sandbox without affecting the host system:

100%
graph LR
    AGENT[Agent] -->|calls tools| SANDBOX[Sandbox environment]
    SANDBOX -->|isolated execution| FS[Sandbox filesystem]
    SANDBOX -->|isolated execution| SHELL[Sandbox Shell]
    SANDBOX -->|isolated network| NET[Sandbox network]
    SANDBOX -.->|not allowed| HOST[Host system]

(2) Sandbox Backend Interface

TYPESCRIPT
interface SandboxBackend {
  name: string
  execute(command: string, options: ShellOptions): Promise<ShellResult>
  readFile(path: string): Promise<string>
  writeFile(path: string, content: string): Promise<void>
  stat(path: string): Promise<FileStat>
  readdir(path: string): Promise<DirEntry[]>
}

(3) Registering a Sandbox Backend

TYPESCRIPT
import { Service, Context } from '@deepseek-ai/cordis'

export default class DockerSandboxBackend extends Service {
  constructor(ctx: Context) {
    super(ctx, 'sandbox')
    
    ctx.implement(SandboxCapability, {
      name: 'docker-sandbox',
      
      async execute(command, options) {
        const container = await this.getContainer()
        const result = await container.exec(command, options)
        return result
      },

      async readFile(path) {
        const container = await this.getContainer()
        return await container.readFile(path)
      },

      async writeFile(path, content) {
        const container = await this.getContainer()
        await container.writeFile(path, content)
      },

      // ...
    })
  }
}

(4) Configuring a Sandbox

YAML
# dsh.config.yaml
sandbox:
  backend: docker
  config:
    image: dsh-sandbox:latest
    workdir: /workspace
    memory: 512m
    cpus: 1
    timeout: 30000
    network: none

6. ctx.sandbox and ctx.shell

(1) ctx.sandbox

ctx.sandbox provides sandboxed file operations:

TYPESCRIPT
export const inject = ['sandbox']

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'sandbox_read',
    description: 'Read file in sandbox',
    parameters: {
      type: 'object',
      properties: {
        path: { type: 'string', description: 'File path in sandbox' }
      },
      required: ['path']
    },
    async execute({ path }, ctx) {
      const content = await ctx.sandbox.readFile(path)
      return { content }
    }
  }))
}

(2) ctx.shell

ctx.shell executes commands inside the sandbox:

TYPESCRIPT
export const inject = ['shell']

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'sandbox_exec',
    description: 'Execute command in sandbox',
    parameters: {
      type: 'object',
      properties: {
        command: { type: 'string', description: 'Command to execute' }
      },
      required: ['command']
    },
    async execute({ command }, ctx) {
      const result = await ctx.shell.execute(command, {
        cwd: '/workspace',
        timeout: 30000
      })
      return {
        stdout: result.stdout,
        stderr: result.stderr,
        exitCode: result.exitCode
      }
    }
  }))
}

(3) sandbox vs Direct fs

Operation Direct fs ctx.sandbox
File paths Host system paths Sandbox-internal paths
Permissions Host user permissions Sandbox user permissions
Isolation None Fully isolated
Performance Fast Slightly slower (through sandbox layer)

(4) Safe Usage Principles

TYPESCRIPT
// ❌ Direct host filesystem access
import { readFileSync } from 'fs'
const content = readFileSync('/etc/passwd')

// ✅ Through sandbox
const content = await ctx.sandbox.readFile('/etc/passwd')
// → If sandbox has filesystem isolation, this call will be restricted

7. Remote Sandbox Configuration

(1) Remote Sandbox Architecture

100%
graph TB
    DSH[DSH Agent] -->|HTTP API| API[Sandbox API Server]
    API -->|manages| CONTAINER1[Container 1<br/>Agent A]
    API -->|manages| CONTAINER2[Container 2<br/>Agent B]
    CONTAINER1 --> FS1[Isolated filesystem 1]
    CONTAINER2 --> FS2[Isolated filesystem 2]

(2) Configuring a Remote Sandbox

YAML
# dsh.config.yaml
sandbox:
  backend: remote
  config:
    endpoint: http://sandbox-server:8080
    apiKey: sk-sandbox-xxx
    defaultImage: dsh-sandbox:latest
    maxContainers: 10
    containerTimeout: 3600
    allowedImages:
      - dsh-sandbox:latest
      - dsh-sandbox-python:latest

(3) Remote Sandbox Backend Implementation

TYPESCRIPT
export default class RemoteSandboxBackend extends Service {
  private endpoint: string
  private apiKey: string

  constructor(ctx: Context) {
    super(ctx, 'sandbox')
    this.endpoint = ctx.config.endpoint
    this.apiKey = ctx.config.apiKey
  }

  async execute(command: string, options: ShellOptions): Promise<ShellResult> {
    const response = await fetch(`${this.endpoint}/execute`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${this.apiKey}`
      },
      body: JSON.stringify({ command, ...options })
    })
    return await response.json()
  }

  async readFile(path: string): Promise<string> {
    const response = await fetch(`${this.endpoint}/read`, {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${this.apiKey}` },
      body: JSON.stringify({ path })
    })
    const data = await response.json()
    return data.content
  }

  // ...
}

(4) Sandbox Lifecycle

TEXT 📖 Display only
1. Agent session created → Request sandbox container
2. Sandbox API creates container → Return container ID
3. Agent operations execute inside container
4. Agent session destroyed → Request container destruction
5. Sandbox API destroys container → Release resources

❓ FAQ

Q Does the approval popup block the Agent?
A Yes. The Agent waits for user approval before continuing. This is intentional — preventing the Agent from executing dangerous operations without user knowledge.
Q Can I skip approval popups?
A Using --preset trusted auto-allows most operations. But not recommended for production.
Q What's the relationship between sandbox and Docker?
A Docker is one sandbox implementation. DSH's sandbox backend interface is generic — it can use Docker, gVisor, remote servers, or any other implementation.
Q What happens without a sandbox configured?
A Tools execute directly on the host system. This is "no sandbox" mode — the Agent has full host permissions.
Q Is remote sandbox latency significant?
A Depends on network and sandbox implementation. Typically file operations 10-50ms, command execution 100-500ms (including startup overhead).
Q How to audit approval decisions?
A Check the approval log, which records each decision's timestamp, operation, policy, and user choice.

📖 Summary


📝 Exercises

1. ⭐ Basic: Configure DSH with the standard preset, try having the Agent execute ls (auto-allowed) and rm (needs approval), and observe the approval popup behavior.

2. ⭐⭐ Intermediate: Add approval rules to a custom tool — SELECT queries auto-allowed, INSERT/UPDATE/DELETE need approval, DROP auto-denied. Test each SQL type's approval behavior.

3. ⭐⭐⭐ Challenge: Implement a simple sandbox backend (using subprocess isolation) and register it with DSH. Have the Agent execute commands inside the sandbox, verifying: 1) file operations are restricted to the sandbox directory; 2) network requests are blocked; 3) files are cleaned up after sandbox destruction.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏