DeepSeek Harness: Sandbox والموافقة
آخر تحديث: 2026-08-31
قوة الوكيل تكمن في قدرته على تنفيذ العمليات، لكن "يستطيع التنفيذ" لا يعني "يجب التنفيذ." سياسات الموافقة هي فرامل الوكيل؛ صناديق الحماية هي أسواره. معًا، يسمحان للوكيل بالتصرف بحرية ضمن حدود آمنة.
📋 المتطلبات المسبقة: إكمال 13-effect.md و 22-capability.md
1. ما ستتعلمه
- سياسة الموافقة
- الإعدادات المسبقة للصلاحيات
- نوافذ الموافقة على العمليات الخطرة
- تسجيل واجهة sandbox الخلفية
- ctx.sandbox و ctx.shell
- تهيئة sandbox بعيد
2. سياسة الموافقة
(1) أوضاع السياسة
يوفر DSH أربعة أوضاع موافقة:
| الوضع | السلوك | الأنسب لـ |
|---|---|---|
always |
سماح دائم، بلا نافذة | العمليات الآمنة (قراءة، بحث) |
ask |
يتطلب موافقة، تأكيد بنافذة | العمليات الخطرة (إنشاء، تعديل، shell) |
ask_with_confirm |
نافذة تأكيد مزدوج | العمليات شديدة الخطورة (حذف، sudo) |
deny |
رفض تلقائي | عمليات يجب ألا تُنفَّذ أبدًا (rm -rf /) |
(2) ▶ مثال 2
# 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) ▶ مثال 3
approval:
tools:
file_edit:
# قائمة بيضاء للمسارات بالسماح التلقائي
auto_allow_paths:
- /tmp/**
- /workspace/**
# قائمة سوداء للمسارات بالرفض التلقائي
auto_deny_paths:
- /etc/**
- /var/**
shell:
# قائمة بيضاء للأوامر
auto_allow_commands:
- ls
- cat
- grep
- head
- wc
- git status
- git log
# قائمة سوداء للأوامر
auto_deny_commands:
- rm -rf /*
- mkfs
- dd if=*
(4) ▶ مثال 4
import { defineTool } from '@deepseek-ai/dsh'
export default defineTool({
name: 'db_query',
description: 'تنفيذ استعلام SQL',
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. الإعدادات المسبقة للصلاحيات
(1) إعدادات مسبقة مدمجة
يوفر DSH ثلاثة إعدادات مسبقة للصلاحيات:
| الإعداد المسبق | الوصف | الاستخدام النموذجي |
|---|---|---|
| trusted | وضع الثقة، معظم العمليات مسموحة تلقائيًا | بيئة تطوير شخصية |
| standard | الوضع القياسي، العمليات الخطرة تحتاج موافقة | التكوين الافتراضي |
| restricted | الوضع المقيد، موافقة صارمة | بيئة الإنتاج |
(2) مقارنة الإعدادات المسبقة
# trusted — وضع الثقة
approval:
tools:
file_edit: always
shell: always
search: always
# standard — الوضع القياسي
approval:
tools:
file_edit:
read: always
create: ask
edit: ask
delete: ask_with_confirm
shell: ask
# restricted — الوضع المقيد
approval:
tools:
file_edit: ask_with_confirm
shell: deny
search: ask
(3) اختيار إعداد مسبق
# اختيار الإعداد المسبق عند البدء
pnpm dsh web --preset trusted
pnpm dsh web --preset standard
pnpm dsh web --preset restricted
(4) إعدادات مسبقة مخصصة
# dsh.config.yaml
approval:
presets:
my-team:
tools:
file_edit:
read: always
create: ask
edit: ask
delete: deny
shell: ask
4. نافذة الموافقة على العمليات الخطرة
(1) آلية النافذة
عندما تتطلب مكالمة أداة موافقة، يُوقِف DSH التنفيذ ويعرض نافذة موافقة:
⚠️ Approval Required: Execute shell command
Command: npm install bcryptjs
Working directory: /home/alice/project
Risk level: MODERATE
[Allow] [Always for npm] [Deny]
(2) خيارات الموافقة
| الخيار | الوصف |
|---|---|
| Allow | السماح بهذه العملية |
| Always | السماح بنوع العمليات هذا (بدون نوافذ بعد ذلك) |
| Always for X | السماح بالعمليات المطابقة لقاعدة محددة |
| Deny | رفض هذه العملية |
(3) الموافقة المجمّعة
يمكن الموافقة على عمليات متعددة دفعة واحدة:
⚠️ 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] 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 الخلفية
(1) مفهوم sandbox
sandbox هو بيئة معزولة لتنفيذ الأدوات — عمليات الوكيل تعمل داخل sandbox دون التأثير على النظام المضيف:
graph LR
AGENT[الوكيل] -->|يستدعي الأدوات| SANDBOX[بيئة sandbox]
SANDBOX -->|تنفيذ معزول| FS[نظام ملفات sandbox]
SANDBOX -->|تنفيذ معزول| SHELL[Shell الخاص بـ sandbox]
SANDBOX -->|شبكة معزولة| NET[شبكة sandbox]
SANDBOX -.->|غير مسموح| HOST[النظام المضيف]
(2) واجهة sandbox الخلفية
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) تسجيل واجهة sandbox خلفية
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) تهيئة sandbox
# dsh.config.yaml
sandbox:
backend: docker
config:
image: dsh-sandbox:latest
workdir: /workspace
memory: 512m
cpus: 1
timeout: 30000
network: none
6. ctx.sandbox و ctx.shell
(1) ctx.sandbox
يوفر ctx.sandbox عمليات ملفات معزولة:
export const inject = ['sandbox']
export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'sandbox_read',
description: 'قراءة ملف في sandbox',
parameters: {
type: 'object',
properties: {
path: { type: 'string', description: 'مسار الملف في sandbox' }
},
required: ['path']
},
async execute({ path }, ctx) {
const content = await ctx.sandbox.readFile(path)
return { content }
}
}))
}
(2) ctx.shell
ينفّذ ctx.shell الأوامر داخل sandbox:
export const inject = ['shell']
export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'sandbox_exec',
description: 'تنفيذ أمر في sandbox',
parameters: {
type: 'object',
properties: {
command: { type: 'string', description: 'الأمر المراد تنفيذه' }
},
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 مقابل fs المباشر
| العملية | fs المباشر | ctx.sandbox |
|---|---|---|
| مسارات الملفات | مسارات النظام المضيف | مسارات داخل sandbox |
| الصلاحيات | صلاحيات مستخدم المضيف | صلاحيات مستخدم sandbox |
| العزل | بلا | عزل كامل |
| الأداء | سريع | أبطأ قليلاً (عبر طبقة sandbox) |
(4) مبادئ الاستخدام الآمن
// ❌ وصول مباشر لنظام ملفات المضيف
import { readFileSync } from 'fs'
const content = readFileSync('/etc/passwd')
// ✅ عبر sandbox
const content = await ctx.sandbox.readFile('/etc/passwd')
// → إذا كان sandbox يمتلك عزل نظام ملفات، ستُقيَّد هذه المكالمة
7. تهيئة sandbox بعيد
(1) معمارية sandbox البعيد
graph TB
DSH[وكيل DSH] -->|HTTP API| API[خادم API الخاص بـ sandbox]
API -->|يُدير| CONTAINER1[حاوية 1<br/>الوكيل A]
API -->|يُدير| CONTAINER2[حاوية 2<br/>الوكيل B]
CONTAINER1 --> FS1[نظام ملفات معزول 1]
CONTAINER2 --> FS2[نظام ملفات معزول 2]
(2) تهيئة sandbox بعيد
# 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) تنفيذ واجهة sandbox خلفية بعيدة
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
1. إنشاء جلسة وكيل → طلب حاوية sandbox
2. API الخاص بـ sandbox ينشئ حاوية → يُرجع معرّف الحاوية
3. عمليات الوكيل تُنفَّذ داخل الحاوية
4. تدمير جلسة الوكيل → طلب تدمير الحاوية
5. API الخاص بـ sandbox يدمّر الحاوية → تحرير الموارد
❓ أسئلة شائعة
--preset trusted يسمح تلقائيًا بمعظم العمليات. لكن غير مُوصى به في الإنتاج.📖 ملخص
- سياسة الموافقة بأربعة أوضاع: always/ask/ask_with_confirm/deny
- الإعدادات المسبقة للصلاحيات: trusted (سماح تلقائي)، standard (تحتاج موافقة)، restricted (موافقة صارمة)
- نوافذ الموافقة تُوقف تنفيذ الوكيل، بانتظار قرار المستخدم
- واجهات sandbox الخلفية تسجّل عبر واجهة SandboxCapability، تدعم Docker/بعيد/تنفيذ مخصص
- ctx.sandbox و ctx.shell تنفّذ العمليات داخل sandbox، معزولة عن النظام المضيف
- صناديق الحماية البعيدة تُدار عبر HTTP API، تدعم عزل حاويات متعددة
📝 تمارين
1. ⭐ أساسي: هيّئ DSH بالإعداد المسبق standard، حاول جعل الوكيل ينفّذ ls (مسموح تلقائيًا) و rm (يحتاج موافقة)، ولاحظ سلوك نافذة الموافقة.
2. ⭐⭐ متوسط: أضف قواعد موافقة إلى أداة مخصصة — استعلامات SELECT مسموحة تلقائيًا، INSERT/UPDATE/DELETE تحتاج موافقة، DROP مرفوض تلقائيًا. اختبر سلوك الموافقة لكل نوع SQL.
3. ⭐⭐⭐ متقدم: نفّذ واجهة sandbox خلفية بسيطة (باستخدام عزل العمليات الفرعية) وسجّلها في DSH. اجعل الوكيل ينفّذ أوامر داخل sandbox، مع التحقق من: 1) عمليات الملفات مقيدة بمجلد sandbox؛ 2) طلبات الشبكة محظورة؛ 3) الملفات تُنظَّف بعد تدمير sandbox.