@gavinc-cn/dsh-path-rules 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 @gavinc-cn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,87 @@
1
- # Temporary Holding Version
1
+ # @gavinc-cn/dsh-path-rules
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ DSH 第五权限模式「路径规则」的逐调用闸门:挂在 `tools/pre-execute` waterfall 上,
4
+ 先 `await next()` 取下游守卫(`dsh-git-guard` / `dsh-readonly-guard` 等)的结论,
5
+ 再按「更严者胜」叠加自己的判定 —— 只可能更严,永不弱化既有守卫。
6
+
7
+ 规则(用户 2026-10-13 定义):
8
+
9
+ - 项目内(= 会话工作区根)目录**可读可写**;
10
+ - 项目外目录**只读**,写入需要用户审批;
11
+ - **白名单**内的目录可读可写(直通,不弹框);
12
+ - **黑名单**内的目录读写**都要审批**(优先级最高,压过白名单与项目内);
13
+ - `bash` / `pwsh`:只读命令直接放行;写入目标可静态解析时按上述规则判定;
14
+ 解析不出的命令默认拒绝并提示模型改写成可判定形式。
15
+
16
+ ## 激活条件
17
+
18
+ 插件**只在预设身份为 `path-rules` 时介入**(`permissionPresets.current(session)`):
19
+
20
+ - 其它四档(`read-only` / `workspace-write` / `danger-full-access` / `auto`)行为一字不变;
21
+ - 子代理(`session.header.origin === 'subagent'`)沿 `parentSession` 上溯取祖先身份
22
+ (框架不向子代理继承非 `auto`/`danger-full-access` 的预设身份);
23
+ - 插件未加载 / `enabled: false` / 服务缺失 / 无 agent 的调用:一律透传,最坏退化成现状
24
+ (沙箱仍把写入限制在会话工作区 + 临时区),不会敞开。
25
+
26
+ ## 判定链(先命中者胜)
27
+
28
+ ```
29
+ 黑名单命中 → ask 白名单命中 → allow 项目内 → allow
30
+ 临时区(/tmp、os.tmpdir())→ allow 项目外读 → allow
31
+ 项目外写 → ask
32
+ shell 判不出 → unanalyzable 策略(默认 deny + 改写指引)
33
+ ```
34
+
35
+ `ask` 走框架标准审批流程(`ctx.approval.request`);会话审批通道为 `never`(子代理被框架钉成
36
+ `never`)时,插件在判定阶段就把 `ask` 改写成 `deny` 并提示回主会话执行 —— 那些会话里没有弹框
37
+ 可弹,只能拒绝。
38
+
39
+ ## 配置(插件 config;机器相关配置写在各 profile 的覆盖行)
40
+
41
+ ```yaml
42
+ - id: dsh-path-rules
43
+ name: "@gavinc-cn/dsh-path-rules"
44
+ config:
45
+ enabled: true # 总开关(false = 完全空转)
46
+ activationPreset: path-rules # 哪个预设身份激活本插件
47
+ whitelist: [] # 绝对路径;可读可写,压过"项目外",但被黑名单压过
48
+ blacklist: [] # 绝对路径;读写都要审批,压过一切
49
+ allowTempRoots: true # /tmp + os.tmpdir() 视为可写(与沙箱口径一致)
50
+ unanalyzable: deny # deny | ask:shell 判不出时的兜底
51
+ failMode: closed # closed | open:插件内部异常时的兜底
52
+ dryRun: false # true = 只记日志不拦(灰度用)
53
+ modelFallback: false # 预留字段:置 true 仅记一条 warn 日志,判定行为不变
54
+ logPath: ~/.kimi-code/hooks/logs/path_rules.dsh.log
55
+ ```
56
+
57
+ 日志事件:`plugin-loaded / allow / ask / deny / pass / dry-run / error`。
58
+
59
+ ## 已知盲区(未覆盖,别当安全)
60
+
61
+ 1. **长驻进程自行写盘**:`bash` 的 `run_in_background`、`job_*` 起的进程在命令文本之外写文件。
62
+ 2. **未受控工具透传**:MCP 工具与未来新增工具若自行写盘,本闸门与沙箱都可能覆盖不到。
63
+ 3. **`glob`/`grep` 的 `pattern` 不是路径**:只对 `path` 参数做黑名单判定。
64
+ 4. **子代理没有审批通道**(框架钉 `approval: never`)⇒ 只能"拒绝",不能"弹框"。
65
+ 5. **编码/不可判定命令**:`-EncodedCommand`、`eval`、超过 3 层的 `bash -c` 嵌套、未闭合引号一律
66
+ 按 `unanalyzable` 处理。
67
+ 6. **读操作不受沙箱保护**:黑名单读的防护 100% 依赖本插件处于激活状态。
68
+ 7. **大小写敏感按平台**:Linux 下按大小写敏感匹配;Windows 桌面端目前**未**实现大小写不敏感回退
69
+ (目录大小写不同但实际相同的路径可能漏判黑名单,已知未覆盖)。
70
+ 8. **跨层分工**:插件批准**不能**突破 `workspace-write` 沙箱(可写根 = 会话工作区 + `/tmp` + `os.tmpdir()`)。
71
+ 项目外/白名单(工作区外)的写会被沙箱拦下,模型需带 `sandbox_permissions` + `justification`
72
+ 重试同一调用以触发框架审批;白名单目标的升权请求由本插件自动答 `allowed-once`(无弹框)。
73
+ 详见 spec §4.4。
74
+
75
+ ## 测试
76
+
77
+ ```bash
78
+ cd packages/runtime/dsh-path-rules
79
+ node --test test/rules.test.mjs test/classify.test.mjs test/analyze-lex.test.mjs \
80
+ test/analyze-bash.test.mjs test/analyze-pwsh.test.mjs test/decide.test.mjs \
81
+ test/plugin.test.mjs test/analyze-security.test.mjs
82
+ ```
83
+
84
+ (Node v24 下 `node --test test/` 目录形式会失败,必须显式给出文件。)
85
+
86
+ 设计文档:`docs/superpowers/specs/2026-10-16-dsh-path-rules-permission-mode-design.md`;
87
+ 实现计划:`docs/superpowers/plans/2026-10-17-dsh-path-rules-permission-mode.md`。