# 产品定位与边界

> **dsh-trust-check 只产出可复核的事实，不下结论。** 它告诉你插件会碰什么、这次升级多碰了什么；不告诉你它安不安全、值不值得装。

本文档说明本项目负责什么、不负责什么，以及集成方（插件市场、目录站点、CI）应该如何使用它的输出。检测规则能证明什么、不能证明什么，见 [THREAT-MODEL.md](../THREAT-MODEL.md)（英文）；JSON 字段契约见 [audit-schema.md](./audit-schema.md)。

## 三层分工

社区里一直有“清理垃圾插件”的诉求。这件事可以拆成三层，每一层由不同的角色负责：

| 层 | 负责方 | 说的是什么 | 说错了是谁的问题 |
|---|---|---|---|
| **事实层** | 本项目 | “声明了 postinstall”“新增了 shell 能力”“未声明仓库” | 事实写错了，是本项目的 bug |
| **策略层** | 集成方（市场、目录站点）与用户 | “默认隐藏有安装脚本的插件”“只看锁了版本的插件” | 过滤规则不合适，由制定规则的一方调整 |
| **背书层** | 具名的人工审阅者 | “某人于某日审阅了 v1.2.3，范围是……” | 审阅结论有误，由审阅者负责 |

本项目只做事实层。策略层和背书层可以建在事实层之上，但不属于本项目，也不会混进本项目的输出字段。

## 本项目做什么

1. **高置信度风险信号**（`redLines`）：安装脚本、覆盖或禁用 `@deepseek-ai/*` 核心 bundle、读到凭据值且有网络访问、明文 HTTP 或字面量 IP 外连。数量刻意保持很少，每一条都应当是“命中即值得停下来看”。
2. **能力披露**（`capabilities` + `evidence`）：shell、文件读写、网络、凭据、环境变量、子代理、LLM 调用、动态代码等，每条附 `文件:行号` 和原文片段。这是给人看的清单，不是裁决。
3. **来源与质量事实**：是否声明仓库、是否锁定版本、入口能否解析等可以离线核对的事实。
4. **升级漂移**：同一个插件在两个版本之间，能力、去向、安装脚本、注入内容发生了哪些变化。这是区分度最高、最不依赖“判断陌生插件好坏”的信号。

对事实层自身的质量要求：

- 高置信度信号的漏报按安全问题处理（报告渠道见 [SECURITY.md](../SECURITY.md)）。
- 读不了、解析不了的内容一律进 `errors`（fail closed），不静默跳过。
- 每条事实都要有稳定标识和可复核的证据。

## 本项目不做什么

- **不下“安全”“可信”“劣等”之类的结论。** `clear` 只表示“这次静态扫描没有检出”，不表示没有风险。
- **不对外提供信任评分。** `score` / `band` 只作为排序等内部用途保留在 JSON 里，设置页不展示，集成方不应据此过滤。
- **不维护插件黑名单或白名单。** 哪些插件该隐藏，是策略层的决定。
- **不提供背书**，也不会自动生成“已审核”“已验证”之类的标记。
- **不下载 tarball、不展开依赖树、不解读技能文本的意图。** 这些是静态分析的边界，见 THREAT-MODEL。
- **扫描引擎不联网。** 发布时间、下载量、npm provenance 等需要联网获取的信息，由调用方作为输入提供，引擎只负责把它们整理成事实。

## 给集成方的建议

以下是建议，不是本项目替集成方做的决定：

- **按事实标识过滤，不按文案或分数过滤。** 当前可以用 `classifyRedLine()` 把 `redLines` 映射成稳定代码（`install-script`、`core-tamper`、`creds-network`、`plaintext-http`、`literal-ip`）。
- **默认规则保持克制。** 默认只处理高置信度信号，其余信号做成用户可以自己打开的开关。
- **信息未知时保持可见。** 扫描失败或数据缺失时，应当标注“未能检查”，而不是猜测成有问题或没问题。
- **文案只写事实，并注明来源**，例如“声明了 postinstall（由 dsh-trust-check vX 检测）”，不要写“危险”“已验证”“安全”。
- **锁定本项目的版本**，并校验 `schemaVersion`。

为什么默认规则要克制：在 0.1.12 对 120 个目录插件的抽样中（样本均为发布到 npm 的插件），约 95% 的插件至少带一项特权能力；结果为“需确认”（没有红线，但带有特权能力）的约占 75%（90 个），仅 shell 能力就出现在约 63% 的插件里。对 DSH 插件来说，“有 shell、网络、文件读写”是常态，单独拿来过滤既没有区分度，也会让用户养成无脑确认的习惯。值得醒目提示的是红线，但其中 `creds-network` 目前达不到“命中即值得停下来看”。同一批样本里 24 个插件命中红线，其中 20 个是“读到凭据值且有网络访问”；在 2026-10 用 0.1.13 扫过的全量目录里，这一类占了全部红线的 73.3%。命中的插件多数是通过官方接口取 key 再联网，静态扫描分不出正常调用和外传。schema 2 仍保留这条红线，检测和文案都不改（见下方路线图）。

## 设置页（插件体检）的定位

设置页是“已安装插件的能力清单 + 升级漂移提醒”，是一个便利功能，不是安全检查：

- 它审计的是**已经安装、已经在运行**的插件，安装脚本可能早已执行；
- 它运行在 DSH 宿主进程里，同进程的其他插件在原理上可以干扰它的结果（见 THREAT-MODEL）。

需要可信结果时，应在宿主之外、安装之前运行 CLI 的 `--dir` 模式。

## 路线图

**已完成（0.1.11–0.1.12）：加固现有事实层**

- 扫描覆盖面上的漏报修复：从入口可达的文件一律纳入扫描或 fail closed；patch 越界或读不出来进 `errors`。
- 扫描上限按真实打包产物调整（单文件 16 MB、总量 64 MB），避免正常插件被判为扫描失败。
- 误报收窄：RFC 1918 内网 IP 只列为去向、不判红线；格式库里的标识 URL 不再算明文外连。
- 对外描述统一为“能力披露”，去掉“信任评分”的说法；CLI 新增可选的 `--exit-code`。

**v2：结构化事实与升级漂移**

- `schemaVersion: 2`（从 0.2.0 起）：新增 `facts[]`，每条形如 `{ id, value, evidence }`；`id` 列表作为对外契约，集成方按 `id` 过滤。升到 2 正是因为 `id` 成了稳定契约，schema 1 的字段没有删改。
- 版本间对比：输入同一插件的两个版本，输出新增或消失的能力、去向、安装脚本、注入内容。
- 允许调用方传入 registry 元数据（发布时间、npm provenance 等），在引擎保持离线的前提下产出来源与维护类事实。
- `decideAckSave` 的 200 分支只返回 `{ status: 200 }`（现在返回的 `entry` 没有被使用，已标记废弃）。
- `creds-network` 继续留在 `redLines`。2026-10 用 0.1.13 扫过的全量目录有 3844 条记录、483 条红线，其中 354 条（73.3%）是这一类。120 个样本里命中的 20 个插件，有 19 个是通过官方接口 `credentials.resolve(` 读取凭据，静态扫描分不出取 key 调自家 API 和外传。收窄成“凭据读取与联网必须在同一文件”只能排除 6 个，而且这 6 个都是把逻辑拆到两个文件里的，拆文件就能绕过；按目标地址收窄又违反“只证明有”。所以 schema 2 不改这条红线的检测，也不改文案。
- `fs-read` 的 `import 'node:fs'` 分支保留。只认调用点会漏掉 `fs['read' + 'File']` 这种写法，导入本身仍是“这个包用了文件系统”的事实。
- 市场上的“本版新增”先不改。目录要先用 `scripts/capability-changes.mjs` 积累几个星期的版本变化；变化率出来之前，不向市场提展示改动。设置页已经在“与上次确认相比”下面列出新增的能力。
- CLI `--exit-code`：人类可读输出默认开启；带 `--json` 时默认不开启，仍可显式传 `--exit-code`。目录探测脚本用 `execFile` 读 stdout，非零退出会在读到 JSON 之前抛错，该插件这次就不会被记录。

**集成**

- 已接入：awesome-dsh-plugin 在目录构建期扫描，只取 `capabilities` / `redLines` 写入目录数据，dsh-market 与目录站陈列事实，区分“未检出”和“未扫描”，不做装前拦截。适配层在对方仓库里单独一个文件，扫描器可替换；是否采用、如何展示由对方决定。
- 本项目这边：维护文案契约（见 [audit-schema.md](./audit-schema.md#wording-contract-capabilities-values-and-redlines-templates)），每次发版在 [CHANGELOG](../CHANGELOG.md) 先列影响目录结果的变更并附样本对比，处理插件作者的误报反馈。
- 之后：CI 场景下，插件升级时自动输出漂移报告，作为回归断言的数据来源。

**有条件再做：社区人工审阅**

只有在社区出现稳定的审阅人、并且撤销与申诉流程明确之后才考虑。即便要做，也会放在独立的仓库里，并满足：

- 每条审阅记录绑定具体的 `插件@版本`，内容变化后自动失效；
- 写明审阅人、审阅日期和审阅范围；
- 可以撤销，有申诉渠道；
- 与本项目的扫描输出分开存放、分开展示。
