Skip to content
dsh.fish
Bundle

dsh-readonly-security-audit

【实验性】只读安全审计模式插件(自动只读、工具级白名单、强制交付选择)· EXPERIMENTAL plugin for the read-only security audit mode (auto read-only, tool allowlist gate, mandatory delivery choice);日常使用推荐 dsh-presets 仓库的原生纯预设版。

Source
my-dsh-plugin
stars
1 stars
License
Apache-2.0
Updated
Updated yesterday

Readme

# readonly-security-audit

English | [中文](README.zh.md)

> ## ⚠️ Experimental — read this first
>
> This is an **experimental, plugin-based** implementation of the read-only
> security audit mode. It exists to try out what a plugin layer can add **on
> top of** a plain preset. For everyday use, prefer the **native preset
> approach**: a pure-preset, script-installable edition lives in the
> [`dsh-presets`](https://github.com/my-dsh-plugin/dsh-presets) repository
> (`readonly-audit/`), needs no custom plugin, and installs with one command
> on any host (bash / PowerShell). See the "Recommended alternative" section
> below.
>
> ### What the plugin layer adds (the experiment)
>
> Compared with the native pure-preset edition, this plugin attempts:
>
> - **Automatic read-only** — entering audit mode switches the session's
>   sandbox to `read-only` by itself, so the deployment does not need to
>   configure `sandbox-policy` to a read-only default;
> - **Tool-level allowlist gate** — an outermost `tools/pre-execute` listener
>   rejects every non-allowlisted tool call, not just filesystem mutations;
> - **Mandatory report-delivery choice** — the model cannot start reading
>   before the user picks conversation or file delivery;
> - **Per-session slash commands** — `/readonly-audit on|off|status`;
> - **One-shot write approval with auto-restore** — an approved report write
>   widens only that single call to `workspace-write` and restores
>   `read-only` immediately after.
>
> These are exactly the capabilities a preset file alone cannot express.
> If they matter to you, install this plugin; otherwise the native preset
> edition below is the recommended, simpler path.
>
> ### Recommended alternative (native preset, scripted install)
>
> ```bash
> bash -c "$(curl -fsSL https://raw.githubusercontent.com/my-dsh-plugin/dsh-presets/main/readonly-audit/install-readonly-audit.sh)"
> ```
>
> Windows PowerShell:
>
> ```powershell
> irm https://raw.githubusercontent.com/my-dsh-plugin/dsh-presets/main/readonly-audit/install-readonly-audit.ps1 | iex
> ```
>
> Trade-off: the native edition has **no automatic read-only** — the
> deployment's `sandbox-policy` default must already be `read-only` (or the
> session must be switched manually), and there is no tool-level allowlist
> gate or mandatory delivery choice. It is still fully read-only at the
> enforcement layer for everything it mounts.

---

A new **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.

## What it does

- The `readonly-audit` agent preset starts the session already in audit mode (`active: true`); no slash command is required to enter it.
- `/readonly-audit off` leaves the mode for the current session and restores its previous sandbox/approval policy; `/readonly-audit on` and `/readonly-audit status` are 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-execute` gate. In audit mode every tool call must be an allowlisted reader (`read`, `read_image`, `glob`, `grep`, `str_replace_editor view`, sandboxed `bash`/`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 to `workspace-write`, and the plugin restores `read-only` immediately 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

1. `readonly-audit/mode` and `readonly-audit/delivery` are durable session events; resume/fork restore them by replay.
2. The session's `sandbox/mode` is set to `read-only`. The stock `dsh-fs-sandbox` and `dsh-bash-sandbox` backends enforce this for filesystem tools and subprocesses.
3. A prepended `tools/pre-execute` listener blocks every non-reader tool call before dispatch. If the mounted shell executor cannot enforce read-only, `bash`/`pwsh` are refused outright.
4. Approved writes are one-shot and one-tool-call only: `workspace-write` is appended after approval, and `tools/post-execute` appends `read-only` again. The built-in `sandbox_permissions` escalation 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:

1. the plugin package into a profile;
2. the `readonly-audit` agent 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:

```sh
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:

```sh
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:

```sh
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:

```sh
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`:

```json
"dependencies": {
  "dsh-readonly-security-audit": "link:/path/to/readonly-security-audit"
}
```

```json
"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:

```text
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:

```sh
cd /path/to/readonly-security-audit

DSH_HOME=/path/to/your-dsh-home \
  node scripts/install-preset.mjs
```

With the default `~/.dsh` home:

```sh
cd /path/to/readonly-security-audit
node scripts/install-preset.mjs
```

Verify it landed in the right home:

```sh
ls "$DSH_HOME/.agent-presets/readonly-audit"
# agent.cordis.yml
# preset.yml
```

Then fully restart the Harness.

### Example: a personal fork

```sh
# 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`:

```sh
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

1. Copy or clone the plugin repository to the new machine, or pack it first:

   ```sh
   cd readonly-security-audit
   pnpm pack --pack-destination /tmp
   # /tmp/dsh-readonly-security-audit-0.1.0.tgz
   ```

2. On the target machine, run the same two steps:
   - install the plugin into the target profile;
   - run `scripts/install-preset.mjs` against the target `DSH_HOME`.
3. Restart and verify below.

The only consistency rule is: **the plugin, the preset, and the Harness process
must all use the same `DSH_HOME`.**

### DeepSeek Harness Desktop — one-shot install

Desktop users need no checkout: the desktop harness (built from the my-dsh-plugin fork) and
its seeded home already ship the `readonly-audit` preset. Run this once in a **normal
terminal** (not inside the app's own harness shell — the app bundle and app-data dir are
sandboxed/read-only from there, especially on macOS):

```sh
bash <(curl -Ls https://raw.githubusercontent.com/my-dsh-plugin/readonly-security-audit/main/scripts/install-desktop.sh) --restart
```

The script is idempotent: pulls the plugin from GitHub (prebuilt `lib/`, nothing to build),
installs it into the desktop web profile, registers the bundle, and restarts the app
(`--restart`). It has no settings namespace, so no allowlist patch is needed. After
restarting, pick **只读安全审计 / Read-only audit mode** from the preset picker on a new
session. Overrides: `DSH_DESKTOP_APP`, `DSH_DESKTOP_HOME`, `DSH_SKILL_SOURCE_DIR`.

> End users of a released desktop build need no manual steps — upgrade and restart; the
> plugin is seeded and the preset is already in the shipped home.

## Use

1. Create a session and select **只读安全审计 / Read-only audit mode** from the preset picker.
2. 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.
3. The assistant reads source, manifests, and configuration, then produces a Markdown security report.
4. For `对话直接回复`, the report appears in the conversation. For `生成报告文件`, the final `write` shows an approval prompt. Rejecting it creates no file; approving it writes only `SECURITY_AUDIT_REPORT.md` in the session workspace.
5. The preset is already read-only; use `/readonly-audit off` only when you deliberately want to leave audit mode for that session.

## Verify and troubleshoot

After restarting, check:

1. The preset picker contains **只读安全审计 / Read-only audit mode**.
2. Creating a session on that preset succeeds.
3. The assistant asks for report delivery before reading anything.
4. An attempted file mutation is rejected with `[readonly-audit] 只读安全审计模式`.
5. A `生成报告文件` write asks for approval; rejecting it creates no file.

If the mode is missing:

```sh
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`:

```yaml
- 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.

```sh
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

Install

dsh plugin --profile web add github:my-dsh-plugin/readonly-security-audit

Profile: web

  • This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source