my-dsh-plugin
readonly-security-audit
DeepSeek Harness 只读安全审计模式 · Read-only security audit mode for DeepSeek Harness
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 15, 2026
- Updated
- Aug 15, 2026
Introduction
readonly-security-audit
A new built-in read-only security audit mode for DeepSeek Harness. It appears in the agent-preset picker beside Standard, PTC, Minimal, and Creator: 只读安全审计 / Read-only audit mode. The assistant may read and analyze code, dependencies, and configuration, while every file mutation is rejected by the system unless the user approves one exact write.
中文:README.zh.md
What it does
- The
readonly-auditagent preset starts the session already in audit mode (active: true); no slash command is required to enter it. /readonly-audit offleaves the mode for the current session and restores its previous sandbox/approval policy;/readonly-audit onand/readonly-audit statusare also available.- Entering the mode writes
sandbox/mode: read-only, so the harness's existing filesystem and process sandboxes reject file writes (write,edit, bash commands that touch files) at the enforcement layer, not by prompt good will. - The plugin also registers an outermost
tools/pre-executegate. In audit mode every tool call must be an allowlisted reader (read,read_image,glob,grep,str_replace_editor view, sandboxedbash/pwsh, web read/search, ask tools) or an explicitly approved single mutation. Everything else fails with[readonly-audit] 只读安全审计模式. - Before the audit starts, the model is forced to call
choose_audit_report_delivery. The user chooses:- 对话直接回复 — the final report is printed in the conversation; no file is created.
- 生成报告文件 — at the end the assistant writes
SECURITY_AUDIT_REPORT.md. That single write is sent through the approval channel; only an explicit user approval temporarily widens the session toworkspace-write, and the plugin restoresread-onlyimmediately after the call.
- The report contract requires, for each finding: problem description, severity, location, evidence, and a text-only remediation suggestion. The assistant never fixes code in this mode.
Why it is enforced, not prompted
readonly-audit/modeandreadonly-audit/deliveryare durable session events; resume/fork restore them by replay.- The session's
sandbox/modeis set toread-only. The stockdsh-fs-sandboxanddsh-bash-sandboxbackends enforce this for filesystem tools and subprocesses. - A prepended
tools/pre-executelistener blocks every non-reader tool call before dispatch. If the mounted shell executor cannot enforce read-only,bash/pwshare refused outright. - Approved writes are one-shot and one-tool-call only:
workspace-writeis appended after approval, andtools/post-executeappendsread-onlyagain. The built-insandbox_permissionsescalation ladder is rejected in audit mode, so an approved report write cannot become full access.
Install on any DeepSeek Harness checkout or fork
This plugin is not tied to one checkout path. The same instructions work for an
upstream checkout, a personal fork such as deepseek-harness-fork, a packaged
Harness install, or another machine.
There are exactly two things to install:
- the plugin package into a profile;
- the
readonly-auditagent preset where the Harness preset roster can see it.
No build is required on the target machine — the repository ships lib/.
1. Install the plugin into a profile
Generic form, using the target checkout's own dsh CLI:
cd /path/to/your-deepseek-harness
DSH_HOME=/path/to/your-dsh-home \
node apps/cli/lib/bin.js plugin \
--profile web \
add /path/to/readonly-security-audit
If your checkout exposes pnpm dsh, the equivalent is:
cd /path/to/your-deepseek-harness
DSH_HOME=/path/to/your-dsh-home \
pnpm dsh plugin add --profile web /path/to/readonly-security-audit
Straight from git:
DSH_HOME=/path/to/your-dsh-home \
node apps/cli/lib/bin.js plugin \
--profile web \
add github:my-dsh-plugin/readonly-security-audit
Offline tarball:
DSH_HOME=/path/to/your-dsh-home \
node apps/cli/lib/bin.js plugin \
--profile web \
add /tmp/dsh-readonly-security-audit-0.1.0.tgz
Manual equivalent in the profile's package.json:
"dependencies": {
"dsh-readonly-security-audit": "link:/path/to/readonly-security-audit"
}
"dsh": {
"profile": {
"bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-readonly-security-audit"]
}
}
2. Make the mode appear in the preset picker
Choose either path. They are interchangeable.
Path A — the checkout already ships the preset
If the target Harness already contains:
apps/cli/config/agent-presets/readonly-audit/
then no preset install step is needed. Install the plugin, restart, and the mode appears as a built-in preset.
Path B — install the preset into the writable user root
This works for forks and older checkouts without touching their source:
cd /path/to/readonly-security-audit
DSH_HOME=/path/to/your-dsh-home \
node scripts/install-preset.mjs
With the default ~/.dsh home:
cd /path/to/readonly-security-audit
node scripts/install-preset.mjs
Verify it landed in the right home:
ls "$DSH_HOME/.agent-presets/readonly-audit"
# agent.cordis.yml
# preset.yml
Then fully restart the Harness.
Example: a personal fork
# 1. Install the plugin into the fork's web profile
cd /path/to/deepseek-harness-fork
DSH_HOME=/path/to/fork-dsh-home \
node apps/cli/lib/bin.js plugin \
--profile web \
add /path/to/readonly-security-audit
# 2. Install the preset into that same DSH_HOME
cd /path/to/readonly-security-audit
DSH_HOME=/path/to/fork-dsh-home \
node scripts/install-preset.mjs
# 3. Restart the fork
cd /path/to/deepseek-harness-fork
DSH_HOME=/path/to/fork-dsh-home \
node apps/cli/lib/bin.js web
If you prefer the mode to look like a built-in fork preset, copy the preset
directory into the fork instead of using DSH_HOME:
mkdir -p /path/to/deepseek-harness-fork/apps/cli/config/agent-presets/readonly-audit
cp /path/to/readonly-security-audit/presets/readonly-audit/* \
/path/to/deepseek-harness-fork/apps/cli/config/agent-presets/readonly-audit/
Migrating to another machine
-
Copy or clone the plugin repository to the new machine, or pack it first:
cd readonly-security-audit pnpm pack --pack-destination /tmp # /tmp/dsh-readonly-security-audit-0.1.0.tgz -
On the target machine, run the same two steps:
- install the plugin into the target profile;
- run
scripts/install-preset.mjsagainst the targetDSH_HOME.
-
Restart and verify below.
The only consistency rule is: the plugin, the preset, and the Harness process
must all use the same DSH_HOME.
Use
- Create a session and select 只读安全审计 / Read-only audit mode from the preset picker.
- Tell the assistant what to audit (for example
请审计当前目录). The assistant must first ask how to deliver the report; it cannot start reading before the user chooses. - The assistant reads source, manifests, and configuration, then produces a Markdown security report.
- For
对话直接回复, the report appears in the conversation. For生成报告文件, the finalwriteshows an approval prompt. Rejecting it creates no file; approving it writes onlySECURITY_AUDIT_REPORT.mdin the session workspace. - The preset is already read-only; use
/readonly-audit offonly when you deliberately want to leave audit mode for that session.
Verify and troubleshoot
After restarting, check:
- The preset picker contains 只读安全审计 / Read-only audit mode.
- Creating a session on that preset succeeds.
- The assistant asks for report delivery before reading anything.
- An attempted file mutation is rejected with
[readonly-audit] 只读安全审计模式. - A
生成报告文件write asks for approval; rejecting it creates no file.
If the mode is missing:
ls "$DSH_HOME/.agent-presets/readonly-audit"
# must contain agent.cordis.yml and preset.yml
If the session fails to find dsh-readonly-security-audit, re-run the plugin
install step against the same profile and DSH_HOME.
Configuration (optional)
The bundle patch inserts the plugin disabled on the host plane; the readonly-audit preset mounts it with active: true. Users can override the report path or allowlist deployment-specific readers in the preset file or in their profile cordis.patch.yml:
- id: readonly-security-audit
name: dsh-readonly-security-audit
config:
active: true
reportPath: reports/audit.md
extraReadOnlyTools: []
extraMutatingTools: []
reportPath must be relative and stay inside the session workspace. To enable the slash-command host instance in other presets, enable the readonly-security-audit row in the profile patch.
Development
Building is only for changing the plugin; consumers use the committed lib/. A sibling deepseek-harness checkout is required for the shared TypeScript preset.
pnpm install
pnpm test # vitest: mode switch + enforcement-fence suites
pnpm typecheck # tsc -b against the sibling harness checkout
pnpm build # tsc declarations + tsdown host entry into lib/
After a build, commit lib/ so installed profiles receive the update with git pull.
License
Apache-2.0