DSH Read-Only Security Audit Plugin: Scans four dimensions—configuration, plugins, sessions, and network—generating desensitized, reproducible, and locatable risk reports. The plugin does not fix issues, connect to external networks, or execute audited plugins.
- Language
- TypeScript
- License
- MIT
- Branch
- main
Install
$ dsh plugin --profile web add github:omdsh-dev/dsh-security-auditRun the command above in your terminal to install this plugin via the dsh CLI. You can switch Profile in the top-right corner. New to dsh? Read the beginner tutorial
Install via your agent
Install the DeepSeek Harness plugin omdsh-dev/dsh-security-audit for me: review the repository at https://github.com/omdsh-dev/dsh-security-audit first, then run the install command and verify the plugin loads successfully.
Paste this instruction to the DSH Web GUI assistant — it will install and verify for you.
One-Line Positioning
DSH Native Security Audit Tool — scans your local DSH environment across four dimensions (configuration, installed plugins, session files, network configuration) in read-only mode, outputs structured risk reports with redacted information, does not auto-fix, does not perform network probing, does not execute audited plugins.
Core Capabilities
- Scans DSH configuration, profile, credential file metadata, detects疑似明文 token/key/私钥、PEM headers, plaintext never enters canonical output, only retains HMAC fingerprint + path + line number
- Audits installed plugins' sources, load paths,
cordis.patch.ymllines, install scripts, sensitive files like.env/.pem/.key, and optional static scanning of plugin source code for dangerous capabilities (eval/child_process/network capabilities) - Checks session directory and file permissions, symlink/reparse escape, session zstd frame structure (truncated by frame budget to defend against decompression bombs)
- Checks listen configuration, external HTTP plaintext endpoints, proxy and credential routing, model discovery targets — all only do configuration-level classification, no active connection or probing
- The aggregated
reportaction merges four scan categories, outputs dual-dimension verdict: risk dimension (fail/warning/pass) + coverage dimension (complete/incomplete), and marks whether truncated due to budget - Provides
rulesaction to real-time list 33 rules' code / severity / criticality / applicable platform
Technical Implementation
- Language: TypeScript (ESM, strict)
- Key Dependencies:
@deepseek-ai/dsh-tools(defineToolregistration);@deepseek-ai/cordis(Cordis container,inject: ['tools']);@deepseek-ai/dsh-invariants(package-owned invariant companion) - Architecture Pattern: Single Cordis plugin registers a tool named
security_audit, exposes a multi-action entry viactx.tools.register(defineTool({...})), output schema is JSON string; injectssecurity-auditrow into host layer stack viacordis.patch.yml - Entry File:
src/index.ts(apply / SecurityAuditConfig), cordis patchcordis.patch.yml, executable compiled entrylib/index.js
Use Cases
When you want to verify "what is the attack surface of my local DSH" after lending your machine to someone, or after installing a batch of new plugins — for example, whether DSH is listening on public network, whether API key ended up in .env instead of credential store, whether the plugin you just installed has install scripts or suspicious capabilities — you can run report once to get dual-dimension verdict and a locatable finding list.
Prerequisites and Compatibility
| Dependency | Minimum Version | Description |
|---|---|---|
| DeepSeek Harness (DSH) | 0.1.0-rc.8 (verified in README) | README.md:86-94 completes type/runtime/tool registration three-stage verification in rc.8 isolated consumer |
| Cordis (host) | ^4.0.1 | package.json peerDependencies, provided by DSH host |
@deepseek-ai/dsh-tools | >=0.0.1-rc.1 <0.2.0 | Provides defineTool registration API |
@deepseek-ai/dsh-invariants | >=0.0.1-rc.1 <0.2.0 | package-owned invariant companion |
| Node.js | ^22.19.0 or >=24.0.0 | package.json#engines mandatory declaration |
| Platform | macOS / Linux / Windows | Cross-platform pure Node script, only uses node:fs / node:os / node:path / node:crypto; permission rules skip on Windows |
| Native Modules | None | Only depends on Node built-in modules, no native binding |
Installation
dsh plugin --profile web add github:omdsh-dev/dsh-security-audit
Configuration Options
This plugin has no user-facing runtime configuration — all visible parameters are security_audit tool call inputs (action / profile / strict / detail / includeSourceScan / root), passed by the caller as needed for each action, no pre-declaration required.
Only administrator-declared "host layer" options (written in the corresponding profile's cordis.patch.yml, passed as plugin initialization inputs, cannot be modified by normal model calls):
| Config | Type | Description | Default |
|---|---|---|---|
allowedRoots | string[] | Additional scannable root paths declarable only by administrators; model parameter root must equal $DSH_HOME or one of the paths listed here, cannot use this field to expand read scope | Undeclared = empty, only $DSH_HOME |
allowedEndpoints | string[] | Administrator-declared endpoint exact whitelist (normalized scheme+host+port, no wildcard/path/userinfo) | Undeclared = empty, all go to default risk rules |
Normal users don't need to write these; they are only used when administrators intentionally want audit to cover multiple root directories or multi-endpoint environments. See src/index.ts:29-42 / src/types.ts:136-156 for details.
FAQ
Q: Will plaintext keys appear in the output report?
A: No. Redactor uses an in-process random 32-byte HMAC key to convert each suspected secret into a hexadecimal fingerprint; the original value is only used for fingerprint calculation, not written to canonical output, and does not appear in error messages or logs (src/redact.ts:83-115); moreover, all secret evidence is forced to carry redacted: true as a protocol field (not a truncation hint). Even if root covers a file containing plaintext, the report will only show "file/line number/type/length/fingerprint".
Q: Will the report modify any local files?
A: No. The design guarantees read-only from the ground up: all paths go through lstat (reject symlink/reparse) → realpath → containment check, root is fixed to $DSH_HOME resolved at process startup, model parameters cannot expand the read scope; the plugin itself does not execute child_process, does not touch ACLs, does not install any dependencies. Source capability scanning is also pure static regex matching — you can verify by running strings lib/index.js | grep chmod.
Q: Why doesn't scan_network do actual port probing?
A: This is an intentional design boundary. scan_network only parses listen / URL / proxy fields in local configuration and classifies them according to spec (loopback / unspecified / private / external), returns unknown-listener-state info finding when unable to determine; it never actively probes or connects to remote targets, so the audit itself does not generate real network traffic, nor will it be misidentified by local IDS.
Q: Can it run on Windows? What differences are there?
A: Yes — the plugin main program is pure Node scripts. But permission rules (credential-file-permissions / session-root-permissions / session-file-permissions) have no zero-side-effect ACL APIs on Win32, so they return skipped(skipReason=platform), not counted as pass; report coverageVerdict will be judged incomplete. This is the "honest judgment" design: better to mark incomplete than to pretend security (src/platform/windows.ts:7-16 / src/runner.ts:138-150).
Q: What does includeSourceScan do? Should I enable it?
A: When enabled, it additionally performs source code regex scanning on each installed plugin (depth 3, skipping node_modules/.git) to match high-risk capability strings like eval / new Function / vm / child_process / spawn / fork / Worker / net|http|https|dgram / fetch / WebSocket. Capability hits never adjudicate malicious, they only state in findings "capability present, intended use requires manual confirmation" — you or your team need to confirm the intent. Therefore it's slower with more false positives; README marks it as optional, default off; recommend enabling only when "just installed an unfamiliar plugin and want to triangulate source credibility".
Q: Is it bad news when report coverageVerdict shows incomplete?
A: It doesn't necessarily mean missed detection. It represents that critical rules could not give conclusions due to skipped (platform unsupported or insufficient permissions) or scanner error — Windows permission rules are a typical trigger. summarize separately counts skipped / errors, combine with checks list to see specific rule names and skipReasons, then decide whether to accept current coverage, run with elevated privileges, or only merge in-domain sub-scan reports.
Q: Should I enable strict mode?
A: For personal self-check, keep default (false) to avoid medium findings alone triggering fail; enable strict in pre-production or CI gate scenarios to treat medium same as high. Prioritize fixing found issues rather than repeatedly re-running — the auditor only diagnoses, does not fix, and does not replace permission boundary and key management specifications.
Q: How to uninstall or downgrade?
A: Use dsh plugin remove security-audit for the corresponding profile; there is no global state in tool call inputs, no daemon, no side effects outside $DSH_HOME; after removal, history only exists in JSON reports you saved. It is v0.0.1, no schema preserved across versions — upgrading just means dsh plugin add to overwrite.
Learning Curve
Advanced — single command to install and directly call report action, but to understand the 33 rules' code/exposure/recommendation from coverageVerdict: incomplete / verdict: fail JSON and fix configurations or swap plugins accordingly requires familiarity with DSH's ~/.dsh directory layout and profile layer stack.
Known Issues and Limitations
- Permission rules always return
skippedon Windows (src/platform/windows.ts:7-16);coverageVerdictmust beincomplete, need independent interpretation inriskVerdictand rule list dimensions - Report capacity has hard limits: single action 10s,
report30s; files ≤ 200, plugins ≤ 200, sessions ≤ 1,000, findings ≤ 1,000; canonical output ≤ 2 MiB; exceeding limits setstruncated:true(src/limits.ts:6-43) - Source capability scanning depth only 3 layers, single file ≤ 1 MiB, cumulative ≤ 64 MiB, only matches
.ts/.js/.mjs/.cjs/.tsx/.jsx; intentionally does not parse AST, no deobfuscation (src/plugins/source-capabilities.ts:20-24, 89-93) - All path operations reject symlink / reparse point; as long as your profile's link field points to a soft link, audit sees not "soft link" but "out-of-root" alert (
src/paths.ts:80-95) - zstd scanning uses self-implemented frame parser to parse header and block header, does not expand block data; so it won't trigger decompression bombs, but also won't give judgment on "whether decompressed content is healthy" (
src/sessions/zstd-scan.ts:1-6, 45-50) scan_networkwill never give real listening state —0.0.0.0config doesn't mean process is really listening, undeclared config doesn't mean it's not listening; this is intentional boundary, explicitly markedunknown-listener-state- Among 31+ different secret patterns, rule
dsh_test_not_a_real_secret_*uses allowlist (src/redact.ts:28-30); other obviously invalid test tokens will also be reported as real secrets — when self-deploying, remember to change tokens in fixtures to this prefix, or add to your own allowlist - Admin-injected
allowedRoots/allowedEndpointsuse exact matching (no wildcard/path/userinfo), entries with these elements are silently considered invalid, never match (src/network/classify.ts:84-96)
DSH 本机安全审计插件 —— 防御性、只读的安全审计:配置、凭据存储元数据、已安装插件来源、关键路径权限、会话文件结构与网络暴露面。输出脱敏、可复现、可定位的风险报告。
仓库:https://github.com/omdsh-dev/dsh-security-audit(public)
动机
DSH 本地环境承载 API Key、token、会话内容和插件加载边界,误配置(服务监听公网、凭据文件权限过宽、插件来源不可信、会话文件结构异常)会造成真实风险。现有工具没有这个视角:
plugin-check只做结构/合规检查——不评估凭据暴露面、危险能力和路径逃逸session-health只做健康诊断——不涉及来源可信度与安全风险裁定- 手工排查不可复现——凭据位置、权限、监听端口、插件来源分散在多处,逐项人工检查极易遗漏且无法留档
本插件以只读方式审计本机 DSH 环境并输出风险报告:不自动修复、不连接远程、不执行被审计插件、不把"没读到"当作"安全"。
安全模型(审计器自身的边界)
- 只读:绝不修改/删除任何文件,绝不执行被审计插件的代码,绝不主动连接远程目标
- 秘密脱敏:疑似秘密只返回类型 / 长度 / 进程内随机 HMAC fingerprint / 路径 / 行号,完整值永不出现在 canonical 输出(设计级保证,非截断)
- 路径围栏:所有路径经 lstat → realpath → containment 检查;
root固定为进程启动时解析的$DSH_HOME(或管理员声明的 allowedRoot),模型参数不能扩大读取范围 - 诚实判定:finding / pass /
skipped/error四态;skipped与error不计为 pass(coverage 降为incomplete);capability finding只提示人工确认、不裁定恶意 - 预算:
- 文件 ≤ 200、插件 ≤ 200、会话 ≤ 1,000、findings ≤ 1,000
- 源码单文件 ≤ 1 MiB(累计 ≤ 64 MiB);canonical 输出 ≤ 2 MiB
- 单 action 10s / report 30s(deadline + AbortSignal 全程检查)
- 工具参数会记入会话日志,不要传入敏感数据
工具声明
注册 security_audit 工具(@deepseek-ai/dsh-security-audit,row id security-audit),统一输出 JSON 文本字符串:所有 action 输出 { tool, version, root, platform, ... } 信封,扫描类 action 带 verdict/riskVerdict/coverageVerdict 与 summary。
| action | 作用 | 输出 |
|---|---|---|
scan_config | DSH 配置、profile、env/credentials 元数据(秘密存在性、权限、外部端点) | findings 含 secretKind/secretLength/fingerprint,无明文 |
scan_plugins | 已安装插件来源、路径、patch、危险静态能力、install script、秘密文件 | capability finding 标注人工确认 |
scan_sessions | 会话目录权限、symlink 逃逸、zstd 帧结构(解压炸弹预算内) | 帧级问题定位到文件 |
scan_network | 监听配置、URL 分类、明文 HTTP、代理路由(不主动联网) | 状态为配置级推断(unknown-listener-state 明确标注) |
report | 汇总四类扫描 | riskVerdict + coverageVerdict 双维度 + findings 汇总 |
rules | 规则目录与适用平台 | 规则 code / severity / critical / platforms |
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
action | string | ✅ | scan_config / scan_plugins / scan_sessions / scan_network / report / rules |
root | string | root 覆盖;必须等于 $DSH_HOME 或管理员声明的 allowedRoot | |
profile | string | 限定单个 profile(^[A-Za-z0-9._-]{1,64}$,不接受路径) | |
strict | boolean | strict 模式:medium finding 也判 fail。默认 false | |
detail | boolean | 详细输出。默认 true;敏感证据始终脱敏 | |
includeSourceScan | boolean | 启用插件静态源码能力扫描(更慢、更多误报)。默认 false |
输出示例
{"tool":"security_audit","version":1,"root":"$DSH_HOME","platform":"win32","strict":false,
"verdict":"fail","riskVerdict":"fail","coverageVerdict":"complete",
"summary":{"critical":0,"high":1,"medium":0,"low":0},
"findings":[{"code":"secret-in-settings","severity":"high","state":"finding",
"evidence":{"path":"$DSH_HOME/.env","line":13,"secretKind":"api-key","secretLength":35,
"fingerprint":"b99e1887d861d7be","redacted":true}}],
"truncated":false}
设计要点
- 脱敏协议:疑似秘密(token/key/private key/密码)在读取后立即以进程内随机密钥做 HMAC fingerprint,原始值只用于指纹计算,不进 canonical 输出;
redacted:true是协议字段而非截断提示 - 路径围栏:所有路径 lstat(拒绝 symlink)→ realpath → containment 三重校验;
root参数不能扩大读取范围(与启动时解析的$DSH_HOME或 allowedRoot 严格相等) - 诚实判定:
skipped(平台不支持/无权限)与error不计为 pass,coverage 降为incomplete;capability finding(源码静态检测到 eval/网络/进程能力)只提示人工确认,不裁定恶意 - 解压炸弹防护:会话 zstd 扫描按帧预算(单帧大小、累计展开比)截断,不整包解压
- 只读保证:无写文件路径、无子进程执行(源码能力扫描只做静态正则,不运行被审计插件)、无网络连接(scan_network 只解析配置与分类 URL,从不探测)
- 可复现输出:无时间戳、无随机路径顺序(稳定排序);超限截断后置
truncated;canonical 输出 ≤ 2 MiB(契约断言)
构建与测试
# 构建(仅需 monorepo 的 tsc)
node <monorepo>/node_modules/typescript/bin/tsc -p tsconfig.json
# 测试(vitest,112 个用例:redact/paths/config/plugins/sessions/network/permissions/report/register)
node <monorepo>/node_modules/vitest/vitest.mjs run tests
npm 0.1.0-rc.8 兼容(已验证)
本插件已迁移到 npm 0.1.0-rc.8 依赖线,并在 @deepseek-ai/[email protected] 的隔离 consumer 中完成全链路验证:
- 类型/运行时:
@deepseek-ai/cordis@^4.0.1+@deepseek-ai/dsh-tools@>=0.0.1-rc.1 <0.2.0+@deepseek-ai/dsh-invariants@>=0.0.1-rc.1 <0.2.0(peer);不再依赖 unscopedcordis - 独立构建:
npm install(devDependencies 自包含 typescript/vitest/@types/node)→npm run typecheck→npm test→npm run build→npm pack - 消费验证:tarball 装入 rc.8 consumer →
dsh --profile compat --dump-config出现本插件 row → 工具真实注册与执行通过 - 启动方式:
npx -p @deepseek-ai/[email protected] dsh web(lib 生产模式;勿install -g全局安装)
安装
DSH 0.1.0-rc.8(npm)下,插件通过 dsh plugin --profile <profile> add <source> 安装,source 支持 GitHub 仓库或 npm pack tarball。
从 GitHub 安装(推荐)
# 交互式(web)profile
dsh plugin --profile web add github:omdsh-dev/dsh-security-audit
# 一次性任务(headless)profile —— dsh run 默认使用 headless
dsh plugin --profile headless add github:omdsh-dev/dsh-security-audit
从 npm pack tarball 安装
npm pack 产物可直接作为 source 安装:
dsh plugin --profile web add dsh-security-audit-*.tgz
包内 dsh.bundle.patch 会在安装后自动把插件加入 profile 的 layer stack(row id:security-audit)。插件缺失的 peer 依赖(@deepseek-ai/cordis、@deepseek-ai/dsh-tools、@deepseek-ai/dsh-invariants)由 profile 的 healed profiles/node_modules 回退安装提供。
⚠️ web 与 headless 是不同 profile:web 安装不会自动覆盖 headless;
dsh run默认使用 headless profile。Windows 路径使用正斜杠(C:/...)。
验证安装
dsh --profile web --dump-config | grep security-audit
运行验证
dsh run "运行 security_audit 的 report 动作,检查本机 DSH 环境安全风险"
旧场景:monorepo / 本地路径安装
monorepo 方式已标注为旧场景(本地 junction/symlink、手动编辑 profile 层、不支持 GitHub/tarball source 的旧快照):
dsh plugin --profile web add "C:/path/to/dsh-security-audit"
许可
MIT
Read the usage guide →
Install steps, key points, FAQ and compatibility for this plugin — auto-derived from indexed fields.
Listing badge
[](https://deepseek-plugin.org/plugins/omdsh-dev/dsh-security-audit)Paste this markdown into your GitHub README to link back to this listing. The badge only states the listing — not a security endorsement.