🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

声明式权限规则 PerryLink/dsh-permission-rules

DeepSeek Harnessv0.7.20
PerryLink2 天前有提交已提供中文文档扫描:含敏感能力需联网

给 DeepSeek Harness 加上 Claude Code 风格的声明式权限规则:在 tools/pre-execute 瀑布流上按顺序匹配 allow/deny/ask 规则,支持工具名、参数(glob/regex)和工作区路径…

59.8/100
综合分
136
GitHub 星标
1,433
npm 周下载
—/5
用户评分

数据截至 2026/11/1 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-permission-rules
npm 源 · dsh-permission-rules 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · security
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-permission-rules @ 0.7.20
✓Node 引擎要求 ^22.19.0 || >=24.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/29 17:41:09

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件
查看扫描证据(共 42 处,展示前 23 条)
  • 读取本地文件
    lib/index.js:2944
    exists: existsSync(path),
  • 读取本地文件
    lib/index.js:3143
    procVersionText = readFileSync("/proc/version", "utf8");
  • 读取本地文件
    lib/index.js:3253
    if (existsSync(candidate)) sources.push(candidate);
  • 读取本地文件
    lib/index.js:3261
    if (existsSync(projectPath)) return [projectPath];
  • 读取本地文件
    lib/index.js:3269
    if (existsSync(fallbackPath)) return [fallbackPath];
  • 读取本地文件
    lib/index.js:3324
    const text = readFileSync(path, "utf8");
  • 写入本地文件
    lib/index.js:4017
    mkdirSync(dirname(path), { recursive: true });
  • 写入本地文件
    lib/index.js:4018
    writeFileSync(path, text, "utf8");
  • 读取本地文件
    scripts/repair-session-logs.mjs:282
    for (const entry of readdirSync(dir)) {
  • 读取本地文件
    scripts/repair-session-logs.mjs:284
    const stat = statSync(full)
  • 读取本地文件
    scripts/repair-session-logs.mjs:295
    const buffer = readFileSync(path)
  • 读取本地文件
    scripts/repair-session-logs.mjs:338
    if (!existsSync(root)) {
  • 写入本地文件
    scripts/repair-session-logs.mjs:381
    renameSync(path, backup)
  • 写入本地文件
    scripts/repair-session-logs.mjs:385
    writeFileSync(path, content)
  • 读取本地文件
    src/remote-service.ts:48
    return { path, exists: existsSync(path), cwd: owner ?? null }
  • 读取本地文件
    src/runtime.ts:128
    procVersionText = readFileSync('/proc/version', 'utf8')
  • 读取本地文件
    src/runtime.ts:257
    if (existsSync(candidate)) sources.push(candidate)
  • 读取本地文件
    src/runtime.ts:265
    if (existsSync(projectPath)) return [projectPath]
  • 读取本地文件
    src/runtime.ts:274
    if (existsSync(fallbackPath)) return [fallbackPath]
  • 读取本地文件
    src/runtime.ts:314
    const text = readFileSync(path, 'utf8')
  • 读取本地文件
    src/runtime.ts:962
    if (!existsSync(path)) return { path, exists: false, text: '' }
  • 写入本地文件
    src/runtime.ts:1015
    mkdirSync(dirname(path), { recursive: true })
  • 写入本地文件
    src/runtime.ts:1016
    writeFileSync(path, text, 'utf8')
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

⚠ 该插件运行需访问外部网络 / 远程 API,部署在国内无外网环境时可能无法正常使用。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-attachment@deepseek-ai/cordis@deepseek-ai/cordis-plugin-include@deepseek-ai/cordis-plugin-loader@deepseek-ai/dsh-agent@deepseek-ai/dsh-brand@deepseek-ai/dsh-client-connection@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-client-ui-slots@deepseek-ai/dsh-client-web@deepseek-ai/dsh-commands
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

2 张 · 点击查看大图

功能亮点

  • 声明式权限规则匹配
  • 按工具名与参数匹配
  • 工作区路径匹配

README

由 DeepSeek 最新模型翻译生成
🛡️ dsh-permission-rules - 1024 store channel:先执行一次 npm i -g dsh1024,再执行 dsh1024 plugin --profile web add dsh-permission-rules(会计入 deepseek1024.com 的安装排行)。 dshfind Claude Code 风格的声明式权限规则,用于 DeepSeek Harness。 规则决定哪些是已知的。审查模型决定哪些不是。 dsh-doctor DSH Market English · 简体中文 · Español · Português · हिन्दी dsh plugin --profile <name> add dsh-permission-rules 📖 生态知识库 —— 实测数据,不是营销话术:插件开发指南 · 插件选型数据 · 维护标准。 安装与卸载 - git channel(最新的 main):dsh plugin --profile web add github:PerryLink/dsh-permission-rules —— prepare 脚本只带生产依赖构建。
展开完整文档(README 剩余 1 节)
🛡️ dsh-permission-rules

- 1024 store channel:先执行一次 npm i -g dsh1024,再执行 dsh1024 plugin --profile web add dsh-permission-rules(会计入 deepseek1024.com 的安装排行)。

dshfind

Claude Code 风格的声明式权限规则,用于 DeepSeek Harness。

规则决定哪些是已知的。审查模型决定哪些不是。

dsh-doctor
DSH Market

English · 简体中文 · Español · Português · हिन्दी

dsh plugin --profile <name> add dsh-permission-rules

📖 生态知识库 —— 实测数据,不是营销话术:插件开发指南 · 插件选型数据 · 维护标准。

安装与卸载

- git channel(最新的 main):dsh plugin --profile web add github:PerryLink/dsh-permission-rules —— prepare 脚本只带生产依赖构建。
- npm channel(已发布的版本):dsh plugin --profile web add dsh-permission-rules。
- tarball channel:在本仓库执行 pnpm pack,然后执行 dsh plugin --profile web add ./dsh-permission-rules-<version>.tgz。
- 卸载:dsh plugin --profile web remove dsh-permission-rules。

⭐ 如果它帮到了你

这个插件是 DSH 插件家族的一员(95 个,全部 Apache-2.0)。如果你在用,给个 star —— 它不会解锁任何功能,但会让下一个人在搜索里更容易找到它。

English: part of a 95 plugin family for DeepSeek Harness. If it is useful, a star helps the next person find it — nothing is gated behind it.

dsh-permission-rules 是什么?

给 DeepSeek Harness 用的 Claude Code 风格声明式权限规则。

规则决定哪些是已知的。审查模型决定哪些不是。

dsh-permission-rules 的工作流图:请求 → 策略 / 审查 → 裁决。

工作流概览:请求 → 策略 / 审查 → 裁决。下面的示例用的是真实命令接口。

兼容性

| 接口面 | 状态 |
| Harness | DeepSeek Harness dsh-v0.2.1-alpha.1(2026-09-22 适配,完整门控链):它的插件配置就是实时设置契约 —— 每个字段都声明为 .volatile(),Loader 按字段给 apply 传实时引用,保存的编辑会提交进运行中的引用,无需重新挂载插件,越界值在写入之前就被 schema 拒绝。Schemastery 早于 volatile()(3.18.3 之前)的宿主仍能挂载并运行这个插件 —— 字段只是保持普通值,实时配置表单不可用 —— 因为标记是通过能力探测施加的,而不是假定存在。这一线上的 Session.append 仍然无法打上 ignorable 标记(它的第三个参数是 surface-intent 包,信封字段只为读取已存日志而保留),所以整个 0.2-alpha 线都预先检查为未标记,会话日志审计默认关闭 —— append 只读 sourceEventSeqs/surfaceOp 并冻结信封,因此它没有任何代码路径能打上这个标记;更早的 0.1.7-alpha(2026-09-22 适配)、0.1.5-rc.2(2026-09-09 适配)和 0.1.3-alpha 线保持同样的仅 surface 的 append 签名,每个 0.2 预发布版都与它们归为一类(STABLE 的 0.2.x 版本留给 append 探测,这样恢复的标记接口面无需新插件版本就能被采用)。这些线的日志迁移即使事件已标记也拒绝未分类的插件事件,所以在 0.1.3-alpha 宿主打开日志之前先 strip 掉 v1 审计行,在 0.1.5-alpha 宿主迁移之前先 strip 掉 v2 审计行(原生 v3 日志只需 repair)。 |
| Node | ^22.19.0 || >=24.0.0 |
| 平台 | 全部(宿主 + Web 设置客户端) |
| 模型 | 任意(deny/ask 原因通过工具结果呈现) |

你能得到什么

dsh-permission-rules 在 tools/pre-execute 瀑布的每次工具调用前放一份有序的 allow / deny / ask 规则列表 —— 确定、即时、可审计,由你用纯 YAML 编写:

- deny 阻止调用;规则的 reason 成为模型可见的错误。
- ask 走官方审批接缝(挂载 dsh-auto-review 让第二模型作答,或由人作答;两者都没有时,harness 失败关闭)。
- allow(以及无匹配)严格通过 next() 委派 —— 下游监听器绝不会被短路。

每次命中和每次放行都会作为 permissionRules/decision 会话事件记入审计日志(仅记录 —— 不会向模型上下文注入任何额外内容)。

- 丰富的匹配能力 —— 工具名 glob(包括 mcp__)、智能体身份选择器(main / subagent / preset:)、参数键/值 glob 或正则(支持 !pattern 取反和 absent 键维度)、任意嵌套深度的工作区相对路径 glob、when 主机条件(环境变量、平台),以及shell 命令分解(argv:命令词、参数 token、管道签名),用于 token 级精确的命令匹配。
- 内置高风险基线 —— 随附一套 deny/ask 规则集(破坏性命令、提权、下载并执行、敏感路径),默认启用,追加在用户规则之后,因此更靠前的用户规则可以覆盖它;用 builtin.enabled 开关。
- 分层规则文件 —— 可选的 searchUp 会从会话 cwd 一路合并到文件系统根目录下的每个 .dsh/rules.yaml,最近的优先。
- 试运行上线 —— enforce: false 只审计策略将会做什么,同时放行每一次调用。
- 热重载 —— Chokidar 监听并防抖;改坏了会保留之前的规则,绝不崩溃。在 WSL 主机上,或规则文件位于 /mnt/<drive> 下时,监听切换为轮询,因为那里的原生变更事件不可靠。
- 大声失败 —— 无效 YAML、未知动作/字段、错误的 glob/正则、易回溯的模式,或规则数超过 maxRules,都会导致加载失败。

规则语法

<project>/.dsh/rules.yaml
rules:
- match: { tools: [bash, pwsh], params: { command: "git push" }, paths: ["/secrets/"] }
action: deny
reason: "No pushes from protected paths"

- match: { tools: [edit, write] }
action: ask
reason: "File writes need confirmation"

- 匹配维度 —— tools(glob,含 mcp__)、agents(main / subagent / preset:<name>;未知身份永不匹配 —— 失败即关闭)、params(键/值 glob 或正则、!pattern 取反、absent 键维度)、paths(在任意嵌套深度提取的工作区相对 glob)、when(env 变量 glob/正则 + 封闭的 platform 列表),以及 network(domains / ips / ports / schemes —— glob、通配符、CIDR、端口范围)。
- 动作 —— allow / deny / ask,按文件顺序求值,首个匹配生效。
- 规则元数据 —— enabled: false(可见但无效)、description、tags;未知字段会导致加载失败。
- Schema —— JSON Schema 随附于 docs/rules-format.schema.json(通过 # yaml-language-server: $schema=... 获得编辑器补全);完整词汇表和 5 条规则的安全基线见 docs/rules-format.en.md。

网络策略

Codex 风格的进程级网络策略:shell 子进程流量走内置的本地 HTTP/CONNECT 代理,每条连接由有序网络规则裁定,或由三种模式裁定,三种模式映射到官方沙箱预设:

- deny-all —— 只读沙箱预设:阻断所有出站。
- whitelist —— workspace-write 预设:放行列出的目标,其余目标按 unlisted: ask(或 deny)处理。
- allow-all —— danger-full-access 预设:全部放行。
- auto(默认)—— 跟随沙箱预设;在没有 sandbox-policy 服务的主机上,解析为 autoFallback(allow-all)。

- 匹配 —— match.network 支持 domains / ips / ports / schemes(glob、通配符、CIDR、端口范围;接受 YAML 数字端口)。在 tools/pre-execute 热路径上提取 URL 候选,触发点是 web 工具参数,以及 bash/pwsh 命令文本里内嵌的 URL;回环目标可按 loopback 策略短路规则。IPv4-mapped IPv6 字面量在匹配前归一化为 IPv4 形式,代理连接的是裁定所依据的地址 —— 绝不做第二次 DNS 解析 —— 裁定未解析出地址的连接按失败关闭处理(502),而不是去拨号主机名。
- 上游链式转发 —— network.upstreamProxy(默认 off)把本代理放行的连接发往上游代理:CONNECT 向上游请求隧道(CONNECT host:port),纯 HTTP 请求以绝对形式转发给它。被阻断的目标永远不会到达上游 —— 它仍然拿到本插件的结构化 403。即使配置了上游,两种情况也绝不链式转发:回环目标(本机之外的代理无法路由它的回环),以及任何由 ips 作用域规则产生的裁定(链式转发会把主机名交给上游,于是「连接落在规则看到的地址上」—— issue #21 —— 恰恰会在规则关心地址的地方不再成立;这些裁定继续直接拨号裁定出的地址),外加 scheme 没有可用上游的目标。上游自己的主机名属于运维配置,不是智能体输入,不受这些规则裁定。带凭据的 URL 绝不原样输出:警告、/rules network 和设置快照都会遮蔽密码(http://user:@host:port)。上游不可达、超时(10 s)或返回非 2xx,一律得到 502* —— 这里刻意不做静默回退到直连,让配置错误保持可见。
- 审计 —— 被拒绝的连接会向所属会话追加 permissionRules/network(同样走自适应 ignorable 闸门),/rules network 和设置页里能看到阻断计数与最近的拦截记录。
- 诊断 —— 被阻断的连接带一条 [network: …] 消息,写明被阻断的目标、做出裁定的模式或规则,以及补救办法。
- 从设置页放行 — 每条最近的拦截都提供 Allow 操作。它会在真正裁决该连接的那个规则文件里,把一条最小规则 match: { network: { domains: [<host>] } } / action: allow 写到顶部(索引 0)。这个文件是:拦截归属工作区的项目文件(配置了绝对 rulesFile 时就用它);或者,对于没有会话的宿主级拦截,是宿主链解析出的文件(绝对 rulesFile → 已存在的 <processCwd>/<rulesFile> → 配置的 fallbackPath → <processCwd>/<rulesFile>,不存在则创建)。加载了多个工作区时,页面先给出选择器,因为任何已加载工作区的链都优先于宿主链。之所以写索引 0,是因为规则先匹配者胜:追加在已有 deny 之后,这条规则就是死文本。只写 domains,因为这个维度包含子域名,且不区分端口和协议,主机下次换端口不会被重新拦截;已有注释和未改动的规则原样保留,文本还要过与手工编辑相同的校验关卡。改动立即生效——缓存的各工作区链和无会话宿主链都会重新读取,不用重启,也不用 /rules reload——并重新计算裁决,所以通知报告的是真实结果,绝不会在连接仍被拦截时声称成功。以下情况会拒绝,文件保持原样:未知工作区、目标不在已知规则源内、只读的内置基线、无法读取或解析的文件;已放行的连接不写任何内容。network.allowHostAction: false 会隐藏按钮,并让 RPC 拒绝。

快速开始

dsh plugin --profile web add github:PerryLink/dsh-permission-rules

1. install the bundle into your profile
dsh plugin --profile web add github:PerryLink/dsh-permission-rules

or from npm (published releases)
dsh plugin --profile web add dsh-permission-rules

2. restart and verify the row
dsh --profile web --dump-config | grep -A4 'id: permission-rules'

示例

这些是插件的真实入口;安装一次,然后调用其中一个。

详细示例

命令

~~~sh
/rules test bash {"command":"git push origin main","cwd":"src/secrets/app"}

输出

~~~text
"bash" matches rule 1 (deny): 禁止 push 到受保护路径

Observed from test/command.spec.ts:204-219 (assertions at :209-213); src/prose.ts:121

失败分支

输入

~~~text
/rules test bash {not json

输出

~~~text
Invalid JSON arguments "{not json": the arguments must parse as JSON.

Observed from plugins/dsh-permission-rules/src/prose.ts:123; plugins/dsh-permission-rules/src/runtime.ts:1266-1272; plugins/dsh-permission-rules/test/command.spec.ts:221-228

简要示例

- tools/pre-execute

配置

所有可调项都是 Schemastery 的 Config 字段,可在 cordis.yml 中修改。按 id 定向的覆盖会替换整行——你需要把用到的每个键都重新写一遍。在 0.1.7-alpha 宿主上,每个字段都声明为 .volatile(),因此也能在 Plugins 设置页就地编辑:编辑会提交到运行中的引用,无需重新挂载插件,运行时在下次使用时读取新值;改动 network.proxyPort、proxyBind、injectEnv 或 noProxy 会立即重新绑定本地代理。数值边界写在 schema 里,配置编辑器在持久化前会按该 schema 校验合并后的配置,所以越界值在写入时就会被拒绝。如果宿主的 Schemastery 早于 volatile(),这些字段就只能改 cordis.yml。

| 键 | 默认值 | 含义 |
| rulesFile | .dsh/rules.yaml | 规则文件位置;相对路径按调用会话的 cwd 解析,绝对路径为全局路径,挂载时校验 |
| fallbackPath | (无) | 按 cwd 发现不到规则文件时使用的规则文件;挂载时校验 |
| badFilePolicy | fail | 规则文件有问题时:fail 让待处理的工具调用直接报错;ignore-with-warning 给出警告并以空规则继续 |
| maxRules | 256 | 生效来源链上规则总数的硬上限 |
| maxCachedWorkspaces | 512 | 按工作区缓存规则加载结果的硬上限(LRU 淘汰) |
| patternMode | glob | params/paths/when.env 的模式风格:glob 或 regex(工具名始终是 glob) |
| watch | true | 用 Chokidar 监听并在变更时重新加载 |
| watchStabilityThresholdMs | 200 | 重新加载的防抖窗口(毫秒) |
| language | en | /rules 输出语言:en、zh、es、pt、hi |
| caseInsensitivePaths | (win32) | paths 模式和工作区根目录比较忽略 ASCII 大小写;Windows 上为 true |
| audit | all | 审计粒度:all 记录每次命中以及放行;hits 跳过放行事件 |
| searchUp | false | 从会话 cwd 向上遍历父目录,合并找到的每个规则文件,最近的优先 |
| maxGlobStars | 2 | 每个 glob 模式中无界 / 量词的硬上限 |
| enforce | true | false = 演练模式:deny/ask 命中会带 dryRun 标记写入审计日志,所有调用都放行 |
| allowUnmarkedAudit | false | 早于标记机制的宿主会丢掉 ignorable 标记;插件会禁用会话日志审计并给出警告。设为 true 可重新启用 |
| network.enabled | true | 代理、环境变量注入和 web 工具模式默认值的总开关 |
| network.mode | auto | 策略模式:auto 跟随沙箱预设,或 deny-all / whitelist / allow-all |
| network.autoFallback | allow-all | auto 找不到沙箱策略服务时使用的模式 |
| network.unlisted | ask | 白名单模式下没有规则匹配的目标如何处理:ask 或 deny |
| network.proxyBind | 127.0.0.1 | 本地代理绑定地址(仅回环) |
| network.proxyPort | 0 | 本地代理端口;0 表示自动选一个空闲临时端口 |
| network.proxyMaxRecent | 100 | 设置页保留的最近拦截记录上限 |
| network.loopback | allow | 回环地址目标:allow(与 Codex 行为一致)或 policy |
| network.injectEnv | true | 是否为子进程注入代理环境变量 |
| network.noProxy | clear | 子进程的 NO_PROXY 处理方式:clear 强制执行策略,preserve 保留原值 |
| network.upstreamProxy | off | 本插件放行的连接所使用的上游代理:off 直接拨号,inherit 复用启动环境里的代理变量名,也可以填一个明确的 http(s):// 代理 URL |
| network.allowHostAction | true | 设置页里针对单条拦截记录的「允许此主机」操作:false 会隐藏 Allow 按钮,并让 permissionRules/allowHost RPC 拒绝执行(规则编辑器不受影响) |
| builtin.enabled | true | 内置高风险基线:false 会完全停用随包附带的 deny/ask 规则集 |
| builtin.path | (随包附带)* | 替换用的基线文件(绝对路径,或相对于 process.cwd());挂载时校验 |

工具与界面

| 界面 | 类型 | 说明 |
| tools/pre-execute | 监听器 | 首个匹配的 allow/deny/ask 规则 + 网络 URL 候选提取 |
| /rules | 命令 | list · reload · decisions [n] · test <tool> <json> |
| permissionRules/decision | 事件 | 只写日志的审计,记录每次命中与放行 |
| permissionRules/network | 事件 | 代理层审计,记录被拦截的连接 |
| HTTP/CONNECT 代理 | 服务 | 内置本地代理,管控 shell 子进程流量 |
| 设置页 | 客户端 | 网络模式编辑器、规则编辑器、拦截计数、最近拦截记录,每条记录带一个允许操作 |

/rules list the active rules, their source files, and any last-reload error
/rules list explicit alias for the bare listing
/rules reload re-read the rule-file chain for this workspace
/rules decisions [n] show the last n permission decisions of this session (default 10)
/rules test <tool> <json> dry-evaluate the rules against a hypothetical call

/rules test 还接受前置参数:--cwd <dir>、--env KEY=VALUE(可重复)、--agent <selector>(可重复)、--platform <name>。在多文件规则链里(例如 searchUp),列出的每一行规则都会标注它来自哪个源文件。

权限与数据

- 权限:在 workshop 清单里声明 files:read、files:watch、files:write、session:append 和 network:outbound。ask 决策走官方审批通道,没有重新实现,也没有绕过。
- 数据:规则文件只从磁盘读取,不写入任何规则数据。不调用模型,不使用审查子代理。
- 会话日志:permissionRules/decision 从不注入模型上下文,追加时带上信封的 ignorable: true 标记,因此任何 harness 构建都能加载这份日志。

安全边界

- 靠策略,不靠内核。 paths 候选只来自一组有文档记录的参数键(任意嵌套深度,深度有上限),并且只有工作区相对路径才会匹配。
- 这里不做审查。 插件从不启动子代理,也不调用模型——给出 ask 决定就是它工作的终点。
- 不改动沙箱。 操作系统级沙箱策略归沙箱接缝管,不归这个插件管。
- 配置错误要大声报错。 未知 YAML 字段、未知动作、错误模式,加载时一律拒绝。
- 回溯有上限。 Glob 模式最多允许 maxGlobStars 次无界星号展开;正则模式会拒绝嵌套的无界量词,以及带量词的重叠字面量交替。
- 拨号失败即关闭。 明文 HTTP 转发和 CONNECT 隧道只连接裁定过的地址;如果某条 allow 的裁定没有解析出任何地址,就按失败关闭处理,返回 502,而不是去拨号那个名字(issue #23)。

已知限制

- 标记前的主机和拒绝插件事件的主机上的审计标记。 permissionRules/decision 追加时带 ignorable: true;如果主机的 Session.append 早于这个标记(0.1.0-rc.1–rc.7 和 0.1.1-rc.1–rc.7 两条线),就会静默丢弃它;0.1.2-rc 线提供的是 alpha.5 接口(没有任何 append 选项会写入这个标记);0.1.2-alpha 线在读取时拒绝插件事件,即使事件带了标记;0.1.3-alpha 和 0.1.5-alpha 线保持同样的仅接口 append 签名(已在发布的 0.1.3-alpha.1/0.1.5-alpha.1 包上验证)——运行时在第一次 append 之前会预先检查以上所有情况,并禁用会话日志审计,同时给出一条一次性警告。跨代迁移同样拒绝带标记的审计行:0.1.3-alpha 的 v1→v2 关卡拒绝未知的 v1 事件,0.1.5-alpha 的 v2→v3 关卡拒绝每一个未分类事件(它的清单冻结在已发布的 v2 词汇表上),所以要在 0.1.3 主机打开日志之前 strip 掉 v1 行,在升级到 0.1.5 主机之前 strip 掉 v2 行。原生 v3 日志接受带标记的插件行,所以它们只需要 repair。把 allowUnmarkedAudit: true 设上即可重新启用;已经写好的日志用 scripts/repair-session-logs.mjs 修复(它的 strip 模式会删掉标记帮不上忙的审计行)。
- 路径候选是启发式的。 只有文档记录的参数键会参与路径匹配,并且只有打开 caseInsensitivePaths 时,工作区相对匹配才做 ASCII 大小写不敏感。
- Glob 是保守子集。 不支持花括号展开——写两条模式,或者改用正则模式。
- 正则回溯防护是结构性的,不是穷尽的。 处理不可信文件时优先用 glob 模式。
- 宿主自身的出站请求不走这个代理。 注入的代理环境变量覆盖的是派生出来的 shell 子进程——注入本来就是为它们准备的——以及任何在请求时读取代理变量名的消费者。它不覆盖宿主进程自己基于 fetch 的流量:启动器在第一个插件挂载之前,就按启动环境装好了 undici 的全局 dispatcher,这个 dispatcher 按自己的策略路由,不看环境变量;而 Node 在启动时采样代理环境,所以之后挂载的插件改不了它。由此带来两个结果:服务商端点不需要放行规则,network.injectEnv: false 也不会把宿主进程从任何东西里摘出去。2026-09-10 在 Node 22 上实测;用 scripts/host-egress-probe.mjs 复现。

- 上游链式代理只覆盖到达这个代理的连接。 在 dsh-v0.1.7-alpha.1 及之后版本,harness 自己的启动时代理策略和它的子进程环境覆盖层可能优先于本插件注入的代理变量名,所以 network.upstreamProxy 描述的是这个代理处理的连接会怎样——它并不声称宿主进程里每条出站路径都如此。

与 dsh-auto-review 协作

- dsh-permission-rules 产出 ask;dsh-auto-review 在 approval/request 瀑布上作答,给出只读的第二模型裁决(或转交人工)。两个都挂载,才能形成完整闭环。
- 已做集成测试:permissionRules/decision → approval/asked → autoReview/verdict → approval/decided,其中审查方替换为脚本化的 mock。
- never 审批策略和官方 harness 的每一项 fail-closed 保证都保持原样。

会话日志修复

在 ignorable 标记出现之前写下的会话日志,可能被较新的 harness 构建拒绝(SessionFormatUnsupportedError)。随附的 scripts/repair-session-logs.mjs 只重写目标审计行,给它们加上 ignorable: true,保持帧结构不变,并做备份:

node scripts/repair-session-logs.mjs scan [--home DIR] # report foreign rows, change nothing
node scripts/repair-session-logs.mjs repair [--home DIR] [--dry-run]
node scripts/repair-session-logs.mjs strip [--home DIR] [--dry-run]

--home 默认是 $DSH_HOME/sessions(或 ~/.dsh/sessions)。每个按代寻址的日志都按它的规范基名发现——session.jsonl、session.v2.jsonl、session.v3.jsonl,每个都可选 .zstd 压缩——所以按代选模式:

- v3(session.v3.jsonl,由 0.1.5-alpha 线原生写入)——读取路径接受带标记的插件行,所以 repair 就够了。
- v2(session.v2.jsonl,由 0.1.3-alpha 线写入)——repair 在写下它的宿主上能打开,但 0.1.5-alpha 的 v2→v3 迁移会拒绝每一个未分类事件,即使带了标记也一样:升级到 0.1.5-alpha 宿主之前,先对 v2 日志跑 strip。
- v1(session.jsonl) — 0.1.3-alpha 的 v1→v2 迁移会拒绝未知的 v1 事件,即使这些事件已标记也不例外:在 0.1.3 或更高版本的主机首次打开日志之前,先运行 strip。

开发

pnpm install # node ^22.19 || >=24
pnpm run typecheck # tsc, src + tests
pnpm run lint # eslint, src + tests + scripts
pnpm test # vitest: 24 spec files
pnpm run test:coverage # coverage gate (90/80/90/90)
pnpm run build # tsc declarations + tsdown bundles (lib/)
pnpm run pack:check # build + pack (the published artifact)
node scripts/check-readme-sync.mjs # five-language README sync gate (also in CI)

无头端到端验证记录见 VERIFICATION.md。

与其他 DSH 插件的互操作性

已针对 DSH 0.2.0-rc.2(本 README 对应的运行时)以及 2026-10-05 调研的高星插件集完成验证。

本插件不会干扰其他插件,包括广泛安装的高星插件:

- 无工具名冲突。 每个工具都带命名空间;没有注册任何由已发布工具或其他插件占用的裸名称。
- 无服务键冲突。 它提供 permissionRules、permissionRulesRuntime;这些键不是内置接缝,调研过的高星插件也都不提供。
- 无插槽冲突。 它不注册任何客户端插槽键,因此不会争抢 shadows-shipped-ui 的席位。
- 无 HTTP 路由冲突。 它不注册任何 webServer 前缀。
- 无补丁层冲突。 打包补丁只 insert 自己的行;从不覆盖内置行的 config。
- 无全局改动。 它不改原型、不改写 process.env、不替换全局 fetch 调度器。

共享事件监听器在构造上互不干扰。 它用 ctx.on() 观察对顺序敏感的事件 tools/post-execute、tools/pre-execute —— 这是 Cordis 的广播注册方式,每个监听器都会执行,谁也无法饿死别人。这里的每个监听器都通过 next() 委托,所以调用链不会被短路;改动施加在 next() 产出的值上,而不是用它替换返回值:
- tools/post-execute —— cc-safety-net(1576★)也在用。
- tools/pre-execute —— cc-safety-net(1576★)也在用。

静态证据:dsh-plugin-doctor 的 K10–K13 在本仓库的每项检查上都报告 pass。

主题

dsh, dsh-plugin, deepseek-harness, permission, policy, allow-deny-ask, approval, safety, network, network-policy, proxy

贡献者

- @am-i-dead —— 把客户端安全的 allow-host 辅助函数从仅主机模块中拆分出来(#24)。

- @PerryLink —— 创建者与维护者:规则词汇与求值、运行时、HMR 监听、会话日志审计、网络策略 + 代理,以及五语言文档。
- @22xuan — 详细报告了 rc.6 宿主会静默丢弃审计事件的 ignorable 标记(#2),并参与了上游 harness 的讨论;v0.4.1 的运行时宿主能力检测和文档修正都直接来自这份分析。
- @sjh9714 — 提出共享的规则语法测试向量语料库(#4、#5),已在 v0.5.1 中随 docs/rule-test-vectors/ 发布,并在设计讨论中提供了 AST 分解的边界用例。
- @weipeng1999 — 提出基于 AST 的命令分解功能建议(#8),该建议促成了上述设计讨论。

- @alexchenzl — the DSH Directory listing request (#7).
- @zl190 — reported and verified the 0.1.0-rc.7 harness compatibility gap (PR #9).
- @cuohua — reported that the 0.1.1-rc line still drops the ignorable marker even though the version gate covered only 0.1.0 (#11); the widened gate drew directly from that analysis.

PerryLink DSH Plugin Family

This project is part of the DeepSeek Harness plugin family from PerryLink. The roster stays collapsed below so every README keeps a short first screen; expand it to see every row and its status.

Expand all plugins

| Plugin | Status |
| dsh-aqua-input-check | |
| dsh-archive-check | |
| dsh-auto-review | |
| dsh-autotier | |
| dsh-bid-ca-precheck | |
| dsh-bid-qual-check | |
| dsh-cert-mcp | |
| dsh-checkpoint-rewind | |
| dsh-click | |
| dsh-composer-history | |
| dsh-contract-stance | |
| dsh-customs-doc-check | |
| dsh-data-quality | |
| dsh-demurrage-ledger | |
| dsh-doublecheck | |
| dsh-drill-script-check | |
| dsh-eia-guide-check | |
| dsh-emergency-plan | |
| dsh-essay-rubric-check | |
| dsh-evidence-check | |
| dsh-export-ctl-check | |
| dsh-fast | |
| dsh-fmea-table-check | |
| dsh-forecast-penalty | |
| dsh-fund-research | |
| dsh-github | |
| dsh-gongwen-flow-check | |
| dsh-gongwen-word-check | |
| dsh-guard-plan-qc | |
| dsh-hazchem-check | |
| dsh-hazplan-check | |
| dsh-hidden-risk-map | |
| dsh-hs-classify | |
| dsh-icd-rule-check | |
| dsh-industry-research | |
| dsh-lawcite-adapter | |
| dsh-laya | |
| dsh-lc-doc-check | |
| dsh-learning-gap-check | |
| dsh-library | |
| dsh-local-ai | |
| dsh-lsp-actions | |
| dsh-mask | |
| dsh-mcp-panel | |
| dsh-medrec-qc | |
| dsh-memento | |
| dsh-nsfc-form-check | |
| dsh-nurse-record-check | |
| dsh-observe | |
| dsh-origin-rvc-check | |
| dsh-ota-review-check | |
| dsh-output-styles | |
| dsh-paper-doc-adapter | |
| dsh-permission-rules | |
| dsh-permit-report-check | |
| dsh-pipeline-check | |
| dsh-pleading-draft | |
| dsh-plugin-doctor | |
| dsh-plugin-guide | |
| dsh-plugin-kit | |
| dsh-plugin-upgrade | |
| dsh-policy-brief-draft | |
| dsh-power-loss-split | |
| dsh-power-ticket-check | |
| dsh-ppap-check | |
| dsh-protest-deadline | |
| dsh-railway-window | |
| dsh-repair-order-qc | |
| dsh-research-report | |
| dsh-review-reply-check | |
| dsh-rulefile-check | |
| dsh-safety-brief-check | |
| dsh-score | |
| dsh-session-sync | |
| dsh-site-log-check | |
| dsh-skill-pack-security | |
| dsh-soe-decision-check | |
| dsh-soilwater-check | |
| dsh-sop-sync-check | |
| dsh-spc-gbt-adapter | |
| dsh-talk | |
| dsh-tender-extract | |
| dsh-tender-matrix | |
| dsh-test-drive | |
| dsh-ticktick | |
| dsh-translate | |
| dsh-warranty-calc | |
| dsh-budget | 🧊 FROZEN — see the repo README |
| dsh-claude-move | 🧊 FROZEN — see the repo README |
| dsh-defend | 🧊 FROZEN — see the repo README |
| dsh-draw | 🧊 FROZEN — see the repo README |
| dsh-reach | 🧊 FROZEN — see the repo README |
| dsh-background-agents | 🚫 RETIRED — see the repo README |
| dsh-session-pin | 🚫 RETIRED — see the repo README |
| dsh-team-rooms | 🚫 RETIRED — see the repo README |

License

Apache License 2.0 © 2026 dsh-permission-rules contributors
预览分享卡片长什么样 ↓PerryLink/dsh-permission-rules
分享 · DeepSeek Harness Hub
PerryLink/dsh-permission-rules

给 DeepSeek Harness 加上 Claude Code 风格的声明式权限规则:在 tools/pre-execute 瀑布流上按顺序匹配 allow/deny/ask 规则,支持工具名、参数(glob/regex)和工作区路径…

回到顶部