Bundle
dsh-dep-vuln-scan
Scan project lockfiles (npm/pnpm/yarn/pip/go/cargo/maven/gradle/...) against the free OSV API and report confirmed dependency vulnerabilities with fix versions and remediation commands.
- Source
- 988hj7tczd-oss
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 5 days ago
Readme
# dsh-dep-vuln-scan
> [!IMPORTANT]
> **依赖前置:相邻 `dsh-src` 检出(`link:` 依赖)**
> 本项目在开发形态下使用 `link:` 依赖指向相邻的 DeepSeek Harness 源码检出(`dsh-src`),
> 与当前仓库保持同一父目录布局(`<parent>/dsh-src`)。克隆本仓库后:
> 1. 先把官方 `deepseek-ai/deepseek-harness` 检出到与本仓库同级的 `dsh-src/` 目录,并执行其 `pnpm install && pnpm run build`;
> 2. 再按下方「安装」一节执行本仓库的 `pnpm install --offline && pnpm build` 与测试。
> 发布到 npm 的版本会尽量把 `link:` 依赖替换为 registry 真实版本;无法替换的内部包保持 `link:`,见各包 README 说明。
DSH(DeepSeek Harness)原生依赖漏洞扫描工具:读取工作区内项目锁文件,调用 **OSV 免费 API**(`api.osv.dev`,无需 key)批量查询漏洞,输出「包 / 当前版本 / 漏洞 ID(CVE/GHSA 优先)/ 摘要 / CVSS / 修复版本」表格 + 汇总 + 修复命令,结果通过 `presentationMeta` 持久化到 `tool/result`,回放可复制。
**只读分析**:不写、不改、不装任何文件 —— 修复命令仅作建议,由用户确认后自行执行(与上游 remediation posture 一致)。
## 功能一览
| 能力 | 说明 |
| --- | --- |
| 生态支持 | npm(`package-lock.json`/`pnpm-lock.yaml`/`yarn.lock`)、PyPI(`requirements.txt`/`Pipfile.lock`/`poetry.lock`)、Go(`go.mod`)、crates.io(`Cargo.lock`)、Maven(`pom.xml`/`build.gradle*`)、NuGet(`packages.lock.json`)、RubyGems(`Gemfile.lock`) |
| 数据源 | OSV `POST /v1/querybatch`,零配置、免费、商用友好 |
| 确认口径 | 仅展示**确认存在**的漏洞:查询带 `version` 让 OSV 过滤 + 本地 `introduced ≤ version < fixed` 区间复核(verifier 口径) |
| 修复信息 | 取 affected ranges 中**最早 fixed**;有修复版标 `√ 有修复版 <版本>`,否则「无修复版」 |
| 严重度 | CVSSv3 数值(≥9 critical / ≥7 high / ≥4 medium / <4 low),无数值时用 OSV qualitative 关键词 |
| effort | `fast`(默认):只查根锁文件、并发 4、无 SBOM;`full`:递归子目录(跳过 `node_modules` 等)、并发 16、生成 SBOM 摘要 |
| 健壮性 | 分块(250/批)批量查询、并发池、30s 超时、2 次重试退避、HTTP 429 按 `Retry-After` 等待;所有失败以结构化 `errors` 返回,不阻塞会话 |
| 持久化 | `output.presentationMeta` 投影整个报告 → `tool/result.meta`,UI 卡片回放可复制 |
## 安装与使用
作为 DSH 插件 bundle 安装进 profile:
```sh
# 1. 构建(产出 lib/,bundle 行引用 dsh-dep-vuln-scan/lib/index.js)
pnpm install && pnpm build
# 2. 加入 profile(声明了 dsh.bundle,dsh 会把本包作为配置层挂载)
dsh plugin --profile demo add ./dsh-dep-vuln-scan
# 3. 验证挂载
dsh --profile demo --dump-config | grep -A2 dep-vuln-scan
```
安装后,模型可直接调用工具(系统提示词已注册引导片段):
```
dep_vuln_scan(path?: string, ecosystems?: string[], effort?: 'fast'|'full')
```
- `path`:项目目录或单个锁文件路径,省略 = 工作区根(自动发现根级锁文件);
- `ecosystems`:过滤(npm / pypi / go / crates / maven / nuget / rubygems,大小写不敏感,也接受别名如 `pip`/`cargo`/`java`);
- `effort`:默认 `fast`;`full` 时递归发现 + 并发 16 + SBOM 摘要段。
## 架构与文件
```
dsh-dep-vuln-scan/
├── cordis.yml # dsh.bundle.patch 层:insert 插件行
├── package.json # dsh.bundle 声明 + exports(./lib/*)
├── src/
│ ├── index.ts # 装配:注册工具 + systemPrompt 引导片段(name/inject/apply)
│ ├── tools/dep-scan.ts # defineTool 定义 + 扫描编排(FsAdapter 注入 + ctx.fs 适配)
│ ├── lockfile-parsers.ts # 各生态锁文件 → [(name, version)](纯函数)
│ ├── osv-client.ts # querybatch 分块/并发/重试/超时/错误分类 + 漏洞归一化
│ ├── report.ts # 报告组装 + render(markdown 表格/汇总/修复命令)+ presentationMeta
│ └── semver.ts # 最小语义化比较(无运行时依赖)
├── tests/
│ ├── smoke.e2e.ts # 27 项离线冒烟/E2E + 1 项 live(网络可用时)
│ └── fixtures/ # npm/pip/go/clean/full 五个 fixture 项目 + 录制 OSV 响应
└── tsconfig{,.build}.json
```
插件模块符合 Cordis 规范:`export const name` / `inject = ['tools','fs','systemPrompt']` / `apply(ctx)`;`ctx.tools.register(defineTool(...))` 与 `ctx.systemPrompt.section({...})` 均为 effect 注册,插件卸载自动清理。
## 为什么用全局 `fetch` 而不是 `ctx.web`
PROMPT 建议走 `ctx.web` seam,但 `dsh-web` 的 fetch seam 只支持对单个 URL 的 GET 检索(返回 HTML/text 正文),不支持 OSV 需要的 `POST /v1/querybatch` + JSON body。因此默认 transport 使用宿主进程全局 `fetch` —— 与内置 `@deepseek-ai/dsh-web-fetch-http` provider 完全相同的传输层 —— 并遵循 seam 的约定:服从调用方 `AbortSignal`、超时合并、结构化错误。transport 本身可注入,测试用本地 stub 覆盖。
## 测试
```sh
pnpm test # 离线:解析器单测 + 录制 OSV 响应走真实客户端代码路径(分块/重试/解析/归一化)
pnpm test:live # 额外跑一次真实 api.osv.dev 查询(网络不可用时自动跳过)
pnpm typecheck
```
- 三种生态 fixture(npm/pip/go)各自断言:命中漏洞、`fixed` 版本、修复命令(`npm install lodash@4.17.21` / `pip install pillow==9.0.0` / `go get golang.org/x/text@0.3.7`);
- clean fixture 断言报告输出 `0 受影响`;
- 无网络(transport 抛错)断言错误信息含「无法访问 OSV,检查网络或稍后重试」且不抛异常;
- fast/full 断言根扫描 1 个锁文件 vs 递归 2 个 + SBOM 差异。
录制 fixture 为「快照式」响应:内容对齐已公开公告(CVE 编号与修复版本为稳定公开事实,测试只断言这些字段),离线可用;需要最新数据时以 `pnpm test:live` 结果为准。
## 已知限制
- `pnpm-lock.yaml` / `yarn.lock` 用行级解析(不引入 YAML 依赖):pnpm 的 peer 后缀、yarn berry(v2+ `__metadata:`)会被跳过,仅覆盖常见形态;
- `pom.xml`/gradle 只识别字面量版本,`${property}` 版本跳过;依赖树传递性不做解析(以锁文件记录为准);
- `requirements.txt` 仅精确 `==` 版本可查,`>=`/`~=`/裸包名跳过;
- 扫描上限:递归深度 8、锁文件 200 个,超大 monorepo 建议按子目录分别扫描。
## License
MIT — 扫描逻辑按 OSV 口径自写;修复建议文案参考 wshobson/agents(MIT)的 remediation posture(只建议、不自动改动)。
## 权限、失败边界与 DSH STORE 状态
- [PERMISSIONS.md](./PERMISSIONS.md):运行时读取面 / 命令面(固定 argv,非 shell)/ 写面 / 外部服务 / 失败边界 / 供应链 / 文件权限信号(无 chmod/chown、644、无 setuid/setgid)。
- [docs/store-evidence.md](./docs/store-evidence.md):一次性 Profile 安装 → 启动(工具注册清单)→ 卸载步骤、本地离线证据、待宿主补录真实运行记录说明,并逐项回应 DSH STORE 五类审查信号(仓库 canonical 匹配 / Node 声明 / 供应链 / 文件权限 / 命令权限)。
- STORE 复检由 dsh-safe-plugin-manager 每 3 小时自动执行;本仓库已按清单契约声明(package.json 的 `repository` / `engines.node` / `dsh.compatibility` / `dsh.permissions`)。
Install
dsh plugin --profile web add github:988hj7tczd-oss/dsh-dep-vuln-scan
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-dep-vuln-scan from the hub
- 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.