DeepSeek Harness Approval: A Human-Machine Handoff, Not a Security Gate

This article dissects DeepSeek Harness's approval mechanism, showing it is a fail-closed human-machine handoff rather than a security boundary, covering its four outcome states, dual approval paths, async Cordis flow, per-package vs future-version authorization, host/client execution split, and orthogonal approval-sandbox knobs.

Shuge Unlimited
Shuge Unlimited
Shuge Unlimited
DeepSeek Harness Approval: A Human-Machine Handoff, Not a Security Gate

The author's core thesis: approval in DeepSeek Harness (dsh) is not a security mechanism but a handoff protocol between human and machine. The mechanism's design — four outcome states, fail-closed defaults, async workflow, and granular authorization — all serve to place a concrete human decision behind every action that reaches the user's environment.

01 Who Asks and When (What Asks)

dsh has two distinct approval mechanisms:

General approval : a shared seam answering "may this operation proceed?" It uses a request/result vocabulary, a dispatcher, a chain of responders, and per-session ask / never policies. Consumers are dsh-tools and dsh-tool-bash; they proceed only on allowed-once.

Cordis dynamic plugin approval : agents can write code via cordis_define (no approval, only validation/registration). Approval triggers at cordis_run only when the package contains browser-side code and has not been approved before.

Typical trigger: sandbox rejects a command (e.g., workspace-write mode blocks writing outside workspace), agent retries with elevated privileges — tool requests approval first, requiring a reason and user consent.

02 Fail-Closed: No Answer Equals Rejection

The general approval path enforces fail-closed at every layer:

Policies : ask (default) sends request down responder chain; first responder wins, no responder → unavailable (treated as rejection). never bypasses dispatch entirely, immediately returns rejected — documented as "strict unattended posture (CI, unattended runs)". Policy is session-scoped, set only via setApprovalPolicy, replayable.

Audit loop : paired events approval/asked and approval/decided; 1:1 alignment, logged but not in model transcript (model sees only derived tool results).

Session guard : request rejected if session not in an active turn; abort signal settles pending request to cancelled, late responses discarded.

No path defaults to allow; allowed-once is the sole outcome requiring explicit evidence.

03 Full Lifecycle of a Cordis Run

cordis_run

is async: the tool returns immediately, the approval card waits for a human.

const requiresApproval = !clientVersionUpdatesApproved
  && !approvedClientPackages.has(packageId)

If the package (this version) lacks single approval, user hasn't enabled future-version approval, and the package ships browser code → approval required.

Tool returns:

{
  "ok": true,
  "status": "awaiting-approval",
  "pluginId": "xxx",
  "packageId": "pkg-1",
  "pluginRunId": "run-1",
  "mode": "run",
  "waitingFor": [],
  "nextPackageId": "pkg-1"
}
ok: true

signals a status, not an error. Model receives this placeholder; system prompt instructs it not to wait, retry, or claim execution is ongoing. Approval card renders in UI.

Human approves → host half starts ( starting-host), then client half ( client-pending), browser loads code → waiting or running. Human rejects → rejected, host never starts.

Result returns to model via async injected message: success reports completion with currentPackageId; rejection reports user declined, advises not to re-request unless user asks.

Only one in-flight activation per plugin; subsequent runs wait for resolution.

04 Single Tick vs Double Tick (Per-Package vs Future Versions)

Two authorization records per plugin:

approvedClientPackages: Set<packageId>  // single: approved packages
clientVersionUpdatesApproved: boolean   // future: this plugin's future versions

Single approval records the packageId; same package re-run passes approvedClientPackages.has(packageId) → no re-prompt.

Dynamic packages are versioned: code change → new immutable package (new packageId). Single tick only covers that exact package; new version prompts again.

Double tick sets clientVersionUpdatesApproved; all future versions of that plugin activate without further prompts.

Authorization is attached to packageId and survives technical failures (re-run after crash doesn't re-prompt). cordis_stop halts execution but preserves authorization; only cordis_undefine (delete plugin) clears packages, authorizations, and version pointers.

05 Execution Location Decides Approval

Approval depends on where code runs, not on perceived danger.

Host half : runs in dsh's Node.js process under node:vm sandbox. Accesses files, network, commands, services, model tools — all server-side resources. No approval needed. Tests assert host-only packages activate directly to running without request.

Client half : runs in browser page. Accesses theme, layout, page state, tool cards. Globals limited to React, console, styles, host; fetch, setTimeout hidden. Approval required because it enters the user's page/session — the user's personal extension.

Browser-side source is not resident; README: "activates with nothing loaded, refresh restores nothing". Page loads code only when asked; refresh zeroes client side while host retains definitions.

This explains the counter-intuitive result: the more dangerous host half (file/command access) is guarded by sandbox and runtime guards; the seemingly benign client half requires human sign-off because it touches the user's persona.

06 Two Orthogonal Knobs

Approval policy and sandbox mode are independent controls:

Knob 1 — Approval policy : ask or never (who decides).

Knob 2 — Sandbox mode : read-only, workspace-write, danger-full-access (what can be touched). Sandbox governs filesystem effects only; network/process visibility excluded. danger-full-access bypasses sandbox entirely.

dsh bundles these into permission presets (UI dropdown). Default presets: workspace-write: sandbox workspace-write + approval

ask
danger-full-access

: sandbox wide open + approval never Second preset: full permissions, approval disabled. Not because it's safe, but because the operator chooses not to ask — typical for unattended CI/scheduled tasks.

Privilege-escalation whitelist ( WIDER_MODES) governs bash upgrades: read-onlyworkspace-write or danger-full-access; workspace-writedanger-full-access only. Only strict widening triggers human prompt; non-widening requests never prompt. "Asking has a cost; avoid when possible."

07 Approval Is Handoff, Not Boundary

Security boundaries are elsewhere:

Sandbox (filesystem isolation)

Execution environment guards (host VM traps, client global whitelist)

Registration boundaries (schema whitelist, runtime guards)

These control what code can touch . Approval controls who authorizes the action . dsh explicitly states: "Restricted execution environment prevents accidental misuse; it is not a security boundary against malicious code. Dynamic code connects to real runtime."

Hence the four outcomes: only allowed-once proceeds; the other three are rejections. Not paranoia — the mechanism's sole duty is to hand the decision to a specific human, then fail-closed. Signature doesn't guarantee correctness, but guarantees a concrete person bears responsibility for allowing it.

Disclaimer : analysis based on source code and docs within authorized scope; no live approval sessions tested. Cordis vs general approval UI convergence not observed; treat as mechanism map, not first-hand test report.

Actionable entry point: search source for the pivot:

grep -n "requiresApproval" packages/extensions/cordis-host-runner/src/index.ts

Two boolean lines and one awaiting-approval — the essence of the human-machine pause. Understanding this beats memorizing ten AI safety slogans.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

AI agent securityDeepSeek Harnessapproval mechanismasync approvalCordis dynamic pluginsfail-closed designhuman-machine handoffsandbox modes
Shuge Unlimited
Written by

Shuge Unlimited

Formerly "Ops with Skill", now officially upgraded. Fully dedicated to AI, we share both the why (fundamental insights) and the how (practical implementation). From technical operations to breakthrough thinking, we help you understand AI's transformation and master the core abilities needed to shape the future. ShugeX: boundless exploration, skillful execution.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.