npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jieai/dsh-plugin-vet

v0.2.5

Published

Plugin trust pipeline for deepseek-harness (DSH): deterministic static scan, runtime guard (T1 sentinel + T2 hooks), audit protocol skill, GUI shield. Alarms by default; N7 confirm-block intercepts confirmed destructive fs ops (family 1/2) by throwing.

Readme

@jieai/dsh-plugin-vet — DSH 插件信任流水线

English | 中文

npm version License: MIT Node

安装任何插件前,先让 dsh-plugin-vet 走一遍:静态规则给出 verdict(确定性、不可伪造), agent 按 vet-audit-protocol 技能排查敏感点与质量问题(谁也无法替代),最终一张评分卡交给人/模型决定。

定位:监控报警器,不是打手。 vet 只做「检查 → 报警 → 给建议」:写时查(静态扫描)、 跑时盯(运行时守卫)、报警面(评分卡 + GUI 盾牌状态灯)。vet 永不替用户动手——不自动卸载、 不自动杀进程、不自动改配置;deny 模式是部署者显式开启的 opt-in,不构成产品身份。最终怎么处置, 由用户在自己的 DSH 上操作决定。

@jieai/dsh-plugin-vet 是 deepseek-harness 生态的信任层插件:占据 下载 → 扫描 → 审计 → 评分 → 决定 → 运行时盯梢 这一整套信任流水线。运行时盯梢内置蜜罐诱饵:谁偷偷翻找密钥文件,当场现形(opt-in,honeypot.enabled)。不做插件市场本体(目录/分发)。


安装

dsh plugin --profile <profile> add @jieai/dsh-plugin-vet

安装即生效链路:pnpm 安装 → reconcilePluginsdsh.bundle → 下次启动 loadProfile 解析 bundle 挂载插件。默认配置见下方 Config(fail-open:只报告不拦截)。

本地 tarball 安装(离线/先验证再发版场景):

dsh plugin --profile <profile> add ./jieai-dsh-plugin-vet-0.1.4.tgz
# 或直接解包到 profile 的 node_modules:
# tar -xzf jieai-dsh-plugin-vet-0.1.4.tgz -C ~/.dsh/profiles/<profile>/node_modules/@jieai/
// 并在 profile 的 cordis.patch.yml 里 insert 挂载条目:
//   - insert:
//       - id: plugin-vet
//         name: '@jieai/dsh-plugin-vet'
//         config:
//           mode: report
//           autoScan: true

路径/相对路径/URL 均可(dsh plugin add 走 pnpm 的 file: 协议兜底,本地 tgz 直接解析)。

首次安装耗时提示dsh plugin add 首次安装到大型 profile 可能耗时数分钟—— 期间 pnpm 会做全量依赖解析、更新 500+ 包的 lockfile 并对整棵依赖树做供应链策略校验 (vet 自身只带 2 个运行时依赖,耗时大头是 profile 已有依赖树的解析/校验,不是 vet)。 校验完成后再次安装/更新只需秒级(复用校验结果)。

兼容性:vet 面向 DSH 0.1.0-rc.6+(peer 范围 ^0.1.0-rc.6)。安装时 pnpm 可能提示 unmet peer dependency——这是预期的:profile 模板 autoInstallPeers: false,运行期从 DSH 安装闭包 ($DSH_HOME/profiles/node_modules 回退层)解析,无需也不能在 profile 里另装一份 cordis 全家桶。

监控范围 = 安装 vet 的 profile。 vet 的守卫是进程内事件(internal/plugin)—— vet 装进哪个 profile,就只守那个 profile 实例加载的插件。多 profile 部署时, 每个要守的 profile 都要装一份 vet(dsh plugin --profile <name> add @jieai/dsh-plugin-vet), 并把 requireAudit 配到对应 profile 的 cordis.patch.yml。

Config(cordis.yml)

| 键 | 默认 | 说明 | |---|---|---| | mode | report | report 只报告不拦截;deny 显式开启拦截 | | autoScan | true | 新插件(internal/plugin)自动静态扫描 | | scannerTimeoutMs | 15000 | 静态扫描子进程超时 | | requireAudit | false | 审计门槛(opt-in):开启后新插件加载时检查 ~/.dsh/vet/audits/ 健康档案——无档案则 report 模式记录黄色 audit-required 告警、deny 模式拦截。档案由 agent 按 vet-audit-protocol 技能审查后手写落盘 | | rules | {}(全开) | 规则开关(R1-R14) | | denyOn | critical | mode: deny 时的拦截阈值 | | allowlist | [] | 包名/插件 id 白名单(跳过扫描) | | runtimeGuard | off | 运行时守卫(性能/稳定代价 opt-in):off 关;watch 启用 T1 哨兵 + T2 钩子,只报警不动作 | | runtimeIntervalMs | 2000 | T1 哨兵 /proc 采样间隔 | | runtimeMemLimitMb | 2048 | T1 内存报警阈值(宿主 VmRSS,超限 → red) | | runtimeForkBurstN | 5 | T1 子进程突增报警阈值(单轮增量,→ red) | | runtimeFdLimit | 512 | T1 文件描述符报警阈值(→ yellow) | | runtimeGrowthMb | 256 | T1 内存持续膨胀报警阈值(完整窗口内 RSS 净增长,→ yellow 疑似泄漏;起窗初期的瞬时尖峰不构成窗口级持续膨胀,不会误报) | | runtimeGrowthWindowMs | 600000 | 膨胀检测窗口(默认 10 分钟) | | honeypot.enabled | false | 蜜罐诱饵(需 runtimeGuard: watch):往 honeypot.dir 放假密钥诱饵,T2 对诱饵路径的触碰(读/写/删)单独报 honeypot 类报警。目录/文件名/内容均无蜜罐关键词(反蜜罐),默认位置 ~/.dsh/.local,诱饵值全是格式正确但无效的假凭据 | | honeypot.dir | '' | 诱饵目录;空 = $HOME/.dsh/.local | | osvCheck | true | 扫描 package.json 时向 Google OSV 查询已知漏洞(仅精确版本查询:range(*、>=、^、~)与无 version 的主包跳过,P3-1/P3-3——避免陈旧全量历史误报;round-7 起 range 不再剥前缀当下界精确版查询);核对面 = 插件自身 + 直接依赖(上限 8 个,@deepseek-ai/* 官方包跳过,P3-10);间接传递树超出 OSV v1 范围与扫描预算。默认开启会外发包名到 api.osv.dev,网络失败静默降级。介意隐私可设 false | | contentBaseline | true | 官方包内容哈希基线(P-5):对每个 @deepseek-ai/* 包的文件计算 SHA-256 并与基线比对——同名冒名包(file:/tarball 无 registry 校验)哈希不符时按最严格 plugin 判定。首次见到自动落盘并信任;基线按 name@version 多版本并存(上限:1000 文件 / 50MB / 10s) | | networkEgress | true | 运行时网络出口观测(P1):包装 http/https/net/http2/tls/dgram/fetch,观测插件发起的出站请求(alarm-only,需 runtimeGuard: watch) | | transitiveDeps | false | 传递依赖 OSV 核对(P1,opt-in,默认关):调用本地已安装的 upstream-radar CLI(绝不 npx 自动安装);未安装/超时/输出形状不符 → 静默降级为仅直接依赖。命中以 OSV-T medium 呈现 | | confirmBlock | block | N7 确认拦截(0.1.14,需 runtimeGuard: watch):只拦不可逆破坏。block(默认)族 1/2 确认即拦;alarm 全族只报警;off 关闭。每次拦截抛错并写一条红色 n7-block 报警;黑名单为进程内存(重启即清) | | confirmBlockFamily3 | alarm | N7 族 3 覆写(系统持久化/提权面写入:bashrc/cron/systemd/ld.so.preload/sudoers.d/profile.d/autostart/authorized_keys/hosts/ssl)。显式 block 为用户自担风险的选择,默认只报警 | | confirmBlockFamily4 | alarm | N7 族 4 覆写(供应链/安装态写入:node_modules 包文件、cordis.patch.yml / cordis.yml / plugin.json)。显式 block 为用户自担风险的选择,默认只报警 |

@deepseek-ai/* 官方包默认豁免(内置信任)。

工具

  • scan_plugin — 确定性静态扫描:target = dynamic-code(源码字符串)/ package(包目录)/ file(单文件)。返回评分卡(verdict + staticScore + findings)。verdict 只由静态规则产出。支持 scanBasisnpm(默认,registry tarball 真实发布物)/ git(仅源码仓,R12 入口/patch 缺失降 info 不误报)。0.1.21 起评分卡能力块含 R16 幽灵/僵尸依赖字段;扫 vet 本体(realpath 判定,非包名)时额外输出 selfScan 注解块——本体自扫呈现 Trusted 卡(① token 级能力声明降级 + ② 每版本产物钉扎 vet-self-pins.json + ④ 发布自扫门禁),普通插件路径行为零变化;原始 findings 原样保留可展开(详见 docs/ARCHITECTURE.md §5.12)。
  • vet_diff — 只读、纯本地:输出某包本地记录过的版本历史 + 最近两版的行为差分(N6)。展示 hosts/fsPaths/spawnCmds/imports 的新增|移除与网络/执行能力翻转。不扫描、不联网。
  • vet_label — 只读、纯本地:输出某包的人类可读"能力营养标签"(M2)——访问的文件(标注敏感路径)、引用的网络主机/子进程、第三方依赖(能力未知)、网络/执行能力标志(含 ESM 具名导入盲区标记),以及最近升级差分摘要。数据源 = 同一份本地 N6 能力清单历史;标签反映的是声明侧静态能力——运行时观测/休眠能力属运行中的盾牌。不扫描、不联网。
  • vet-audit-protocol(技能) — 审查流程协议(AUDIT_PROTOCOL.md):agent 按预设步骤审查新插件——scan_plugin 静态判据(含 R12 Cordis/DSH 契约)→ 读清单/源码 → 逐条核实发现 → 主动深挖(网络/文件/进程/凭据/库语义)→ 契约与代码质量审计(4.5 步:入口/Config schema 一致性、错误处理/同步阻塞/资源泄漏/异步正确性等「写得烂」问题——静态干净≠值得装)→ 用系统写入能力手写健康档案到 ~/.dsh/vet/audits/<plugin>-<version>-<ts>.md。vet 不内置审计工具、不替 agent 调查,只给判据与落盘约定。

自动行为

  • internal/plugin 自动扫描autoScan: true):新装第三方 npm 包加载时自动静态扫描;deny 模式 + verdict ≥ denyOn → 回滚加载。
  • 审计门槛requireAudit: true):无健康档案的第三方插件加载时——report 模式记录黄色 audit-required 告警(进 /vet/status.json 告警列表,插件照常加载);deny 模式回滚加载(引用 vet-audit-protocol 提示先审查)。档案按版本精确匹配(P-1):插件升级后旧版本档案不放行新版本——重新审查才能消除告警/拦截。
  • tools/execute 拦截cordis_define / run_code / workflow 执行前扫描代码字符串(cordis_run 的真实 schema 无 code 载荷,保留守卫位不生效,P3-11 同步);report 模式仅在非 clean 结果时加 VET: 前缀(干净执行不污染机器可读输出),deny 模式直接拦截(isError)。
  • 运行时守卫(runtimeGuard: watch——alarm-only:
    • T1 哨兵:旁路子进程每 runtimeIntervalMs 读宿主 /proc(VmRSS / 子进程数 / fd 数),报警 JSON 行回传宿主 → 盾牌变黄/红。
    • T2 钩子:进程内包装 fs / child_process(含 fs.promises),危险操作(敏感路径写入/删除、读密钥文件、含 shell/下载外联关键词的子进程、蜜罐诱饵触碰、~/.dsh 配置根侦察)取栈归因到插件包名后报警;官方包归因全类降噪(能力授权——官方包是平台本体,高频读写 ~/.dsh 会话/配置/存储不刷屏;第三方无法伪造归因)。从不阻断调用。自伤豁免(实测误报后修复):
      • node_modules 包目录豁免:包名/包内文件是公开工件——含 credential/secret 等词的包名是正常生态(@aws-sdk/credential-provider-*@deepseek-ai/dsh-credentials-local 等),宿主模块解析(require.resolve 内部 realpathSync/stat 包内 package.json)与 vet 扫描读取都会高频触碰,不再误报 fs-probe;node_modules 之前的段照常判定(~/.ssh/node_modules/x 仍命中 .ssh),写删系统根(/usr 等)仍报警。
      • 归因排除 vet 自身:包装器帧永远是报警栈栈顶,vet 根不参与归因映射——宿主/无主报警不再栽到 vet 头上(报警照发,归因到真实调用方)。
      • 工具链临时产物(tsc <源名>.<pid>.<uuid>.tmpdir*.tmp*.temp*.swp 等)自动豁免——名字里的 secrets/credentials 只是被编译的源文件名,删它是清理不是破坏;父段照常判定(~/.ssh/config.bak 仍报警)。
  • GUI 盾牌:浏览器半区注册进 conversation.session.header.actions,轮询 /vet/status.json 显示绿/黄/红灯 + 报警计数。激活需 dsh web 重启(重启后 client-modules 才扫描到 dsh.client 声明)。
    • 交互:可点击——点击展开报警面板(实时指标:内存/CPU/I-O/子进程/fd;守卫状态:未开启时可一键写入 runtimeGuard: watch 配置(重启生效);报警列表含严重度/归因/逐条建议;最近扫描回显、刷新、更新时刻),外部点击自动关闭;有报警时盾牌旁显示计数徽标(绿/黄/红主题色,明暗自适应)。
    • 单条忽略:每条报警可点「忽略」——只影响展示(不再计入盾牌等级与计数),记录保留可随时「恢复」;报警停止后忽略自动失效,将来复发会重新可见(可再忽略)。忽略状态与报警存储同生命周期(重启即重置)。鉴权边界(P3-12 记录):dismiss/restore 仅做同源校验(alarm-only 展示层风险——同源页面脚本可隐藏报警,但记录不删、不影响其他能力,体系内可接受)。
    • 展示上限:面板展示最近 8 条报警;存储为环形缓冲上限 20 条,同 id 60 秒内去重,24 小时 TTL 过期(持续触发会自然续期)——100 条不会全量展示,也无需展示(新报警会顶掉最旧的)。最近扫描回显(suspicious → 黄灯)同样按 24h TTL 过期(P3-2:一次可疑扫描不再永久黄,持续扫描自然续期)。

静态规则表(R1-R16)

| ID | 名称 | 默认级别 | 适用场景 | 确定性 | |---|---|---|---|---| | R1 | constructor 链逃逸 | critical | code + files | certain/likely | | R2 | 动态执行(eval/Function/import/require) | high(files)/ medium(code;bin 入口降 medium) | both | certain/likely | | R3 | process 直接访问(按 runtime 分级;只读成员/generic/bin 入口/应用型包 → info) | critical(host)/ high(sandbox) | both | certain | | R4 | 宿主闭包捕获(agent/TextEncoder…)+ 宿主全局原型污染 | critical(code)/ high(files,与 targetKind 无关) | both | certain/likely | | R5 | ctx 逃逸尝试信号(withheld 成员/未声明服务;ctx.logger 等官方注入服务白名单放行) | medium | 仅 code | likely | | R6 | 字符串粗扫兜底(混淆特征需与动态执行组合证据) | info | both | heuristic | | R7 | 硬编码密钥 | high | both | likely | | R9 | 资源安全(无界分配/无出口同步循环/循环内 spawn/ReDoS/递归无终止/循环内增长模式) | high(分配/死循环/fork)/ medium(ReDoS/递归/Map.set)/ info(常驻循环/+=/Promise.all) | both | certain/likely/heuristic | | R10 | 供应链(package.json install 钩子/依赖清单) | high(install 钩子)/ info(依赖清单) | files | likely/heuristic | | R11 | 破坏性文件操作(fs 删除/敏感路径读写) | high(敏感路径)/ medium(删除) | both | likely | | R12 | Cordis/DSH 契约(入口文件/bundle patch 声明/name/engines.node) | high(patch 缺失/入口缺失)/ medium(无入口/缺 name)/ info(node 版本低) | files | certain/likely | | R13 | 网络外联端点(字符串字面量中的 Discord/Telegram/Slack webhook、云元数据端点 169.254.169.254 / metadata.*.internal / 100.100.100.200、.onion 目标) | high | both | likely | | R14 | 随包分发的非 JS 脚本下载即执行(.sh/.bash/.ps1/.cmd/.bat 中 curl|sh、wget|sh、编码 PowerShell -enc/IEX、certutil/bitsadmin/mshta/regsvr32/rundll32 等;generic → info) | high(plugin)/ info(generic) | files | likely | | R15 | 动态网络目标(fetch / WebSocket / http(s).request|get / net.connect 的目标参数静态不可解——"刻意遮蔽"目标) | info(观测;叠加 N1 隐能力等信号才抬升) | both | heuristic | | R16 | 依赖一致性审计:幽灵依赖(代码引用但 package.json 未声明,靠传递依赖提升侥幸可解析)与僵尸依赖(package.json 声明但 node_modules 缺失) | info(观测;永不进 verdict) | files | heuristic |

评分模型

staticScore = max(0, 100 - Σ(severity 权重 × 命中数 × confidence 系数))

verdict(唯一权威判定,heuristic 永不升级):critical ≥ 1 → critical;否则 high ≥ 1 → suspicious;其余 → cleanverdict 只由静态层产出:staticScore 与 verdict 分开呈现,不合成单一总分。

能力边界(诚实清单)

静态扫描是"减速带 + 取证层",不是安全边界。以下按判定影响分两档, 并如实列出明确不检测的形态(均已实测验证)。

能检测 —— 判定级(会改变 verdict)

| 规则 | 检测的问题类 | 命中 → verdict | 验证 | |---|---|---|---| | R1 | 构造器链逃逸:x.constructor("return process") / x["constructor"]("return " + "process") / new (globalThis.constructor.constructor)("return process")()(点/元素访问 + new 形态;字符串参数静态可求值:字面量/模板/拼接/const 绑定;new 支持 const 别名追踪) | critical | 矩阵 + 多文件 ✓ | | R2 | 动态执行:eval() / Function() / new Function/`new AsyncFunction`(含括号形态 new (Function)(...);参数含逃逸串 → critical)/ (async)=>{}.constructor 捕获(round-7.2:new X.constructor 仅 base 为函数字面量才报——new n.constructor(n.type, n) 对象克隆形态不报)/ vm.runInContext/`runInNewContext` / 动态 import() / require() | high(files)/ medium(code,逃逸串 critical);bin 入口文件按通用代码判定降 medium | 矩阵 + round-7/7.2 回归 ✓ | | R3 | process 直访:getBuiltinModule/`mainModule`/`module`/`exit`(含 reallyExit)→ critical;副作用成员(kill/abort/chdir/umask/setuid/dlopen/binding 等)与未知成员 → high;只读成员(round-7.1)env/cwd/platform/pid/argv/execPath/stdin/stdout/stderr/nextTick/on 等 → info 能力触达面(读 cwd/env/pid 不是逃逸通道,bridges 类无 bin 的 MCP/工具插件不再误伤);runtime='sandbox' 封顶 high;形态降级:generic 包 / bin 入口文件 / 应用型包 → info | critical / high / info | 矩阵 + round-7.1 回归 ✓ | | R4 | 宿主闭包捕获:agent/parallel/pipeline/phase/log/TextEncoder/TextDecoder/btoa/atob 的 .constructor 读取或 Object.getPrototypeOf 投喂(code 场景);宿主全局原型污染:<内置>.prototype.<成员> = ... 覆盖赋值与 Object.defineProperty(<内置>.prototype, ...)(Object/Array/String/Function/TextEncoder/URL/Buffer 等 40+ 内置,round-7) | critical(code)/ high(files,round-7.1 起与 targetKind 无关——污染语义不分插件/通用包,generic 不再降 info) | 矩阵 + round-7 回归 ✓ | | R7 | 硬编码密钥:sk- / AKIA / AIza / gh[pousr]_ / xox[baprs]- / 环境变量赋值 / URL 内嵌 key(占位符排除) | high → suspicious | 矩阵 ✓ | | R9 | 资源安全:new Array(2**31) / Buffer.alloc(1GB) 无界分配(≥1e8)、while(true)/for(;;) 无出口同步循环(卡死宿主;round-7.2:带标签 break 跳出外层循环算出口——outer: for(;;){ ... break outer } 不再误报)、无出口循环内 spawn/exec/fork/new Worker(fork 炸弹) | high → suspicious;ReDoS 嵌套量词 (a+)+ 类与 alternation 分支重叠 (a|aa)+ → medium(分支首字符互斥的 (?:[^']|'')* 类、组后 ?(https?:)? 类线性回溯不报,round-7)、递归无终止(for-of/for-in 集合遍历与带条件循环内的自调用不报,round-7)、循环内 Map.set → medium(不进 verdict);含 await 常驻循环仅 info(§14.1 不短路审查) | 矩阵 + round-7/7.2 回归 ✓ | | R10 | 供应链:package.json scripts 的 preinstall/install/postinstall/uninstall 钩子(安装期任意代码执行)→ high;依赖清单 → info(已知漏洞核对:OSV 精确版本查询,osvCheck 可关) | high → suspicious(install 钩子) | 矩阵 ✓ | | R11 | 破坏性文件操作:fs.unlink/rm/rmdir(+Sync) 删除敏感路径(/etc/root/.ssh 等)→ high,普通删除 → medium;fs.writeFile 等写入敏感路径 → high;fs.readdir 遍历敏感目录 → medium | high → suspicious(敏感路径);medium 不进 verdict | 矩阵 ✓ | | R12 | Cordis/DSH 契约:dsh.bundle.patch 声明的文件缺失 → high;无 入口(无 main/exports["."] 且根无 index.js)→ medium;声明的入口文件缺失 → high;插件意图包缺 name → medium;engines.node 主版本低于 22 → info | high → suspicious(声明即挂载点/入口,缺失必失败);medium/info 不进 verdict | 矩阵 ✓ | | R13 | 网络外联:字符串字面量中硬编码 Discord/Telegram/Slack webhook、云元数据端点、.onion 目标 | high → suspicious | 矩阵 + R13 测试 ✓ | | R14 | 非 JS 脚本:.sh/.bash/.ps1/.cmd/.bat 中 curl|sh、wget|sh、PowerShell 下载管道/-enc/IEX、certutil/bitsadmin/mshta/regsvr32/rundll32(generic → info) | high → suspicious(plugin);info 不进 verdict(generic) | 矩阵 + R14 测试 ✓ |

能检测 —— 提示级(只降分,永不改变 verdict)

| 规则 | 检测的问题类 | 说明 | |---|---|---| | R5 | ctx 逃逸尝试信号:访问沙箱 withheld 框架成员/未声明服务(ctx.plugin 等) | 仅 code 场景;medium | | R6 | 字符串粗扫:拼接逃逸特征、getBuiltinModule/`child_process`/危险 require 模块引用、混淆特征(String.fromCharCode/`Buffer.from(base64)`/`atob(`/`charCodeAt`——round-7 起需与同文件动态执行信号(eval/new Function/vm 等)组合才报,终端协议/编码类常规字节处理不再误报) | info/heuristic | | R8 | 扫描超时/文件过大跳过 | info 元规则 |

运行时监控(runtimeGuard: watch 时启用)——只报警

| 层 | 机制 | 能抓 | 局限 | |---|---|---|---| | T1 哨兵 | 子进程轮询宿主 /proc | 内存炸弹(>memLimit)、内存持续膨胀(泄漏,窗口净增长按倍数报警)、fork 炸弹(子进程突增)、fd 激增 | 粒度=宿主全局(插件共用进程,无法归因到插件) | | T2 钩子 | 进程内包装 fs/child_process(含 fs.promises) | 敏感路径写入/删除(/etc、~/.ssh、.env…)、读密钥文件、含 shell/下载外联关键词的 spawn | 栈归因 best-effort;每次调用包装开销(I/O 密集 <5%,热点 10-20% 级) | | N1 能力差分(0.1.13) | 声明能力清单(扫描时注册)vs 运行时观测(T2) | 隐能力被执行(观测到敏感动作但静态足迹为零含 imports)→ red n1-hidden;imports 非空 ⇒ 「能力未知」保守覆盖;只敏感动作参与 | 需先扫过该插件(自动扫描注册);静态可见未触发的能力记为休眠,展示于营养标签(M2,0.1.16) | | N3 外泄/破坏台账(0.1.14) | 按插件字节计数(敏感读/网络写,生命周期累计)+ 10s 破坏签名窗 + 序列签名(读密钥→spawn curl/wget/nc、读密钥→网络写) | 读完就发:双计数>0 → 黄 n3-exfil,量级接近 → 红 n3-exfil-match,序列命中(30s 窗)→ 红;破坏族:批量删/改名加密标记/同路径读后覆盖写/写放大 → 黄,两个以上叠加 → 红 n3-ransom;蜜罐/金丝雀确认(N4)插件阈值降最低 | 不检查会话内容(只字节+操作形态);跨会话/超慢外泄、原生二进制内部、fd 级读取、fetch body 不计(已记边界);归因 best-effort | | N4 蜜罐水印(0.1.14) | 诱饵值内嵌高熵金丝雀(内存集合);网络 URL/body(write/end)、dgram、fetch URL/body、spawn 参数扫描 | 出站命中 → red canary-leak(100% 外泄确认;直接/URL-decode/一次 base64-decode 变体;涉事插件标记 N3 疑似) | 只确认蜜罐材料外泄;金丝雀分片重组不防(已记边界);需蜜罐诱饵(幂等诱饵保留金丝雀) | | 完整性金丝雀(0.1.14) | ~/.dsh 下落地少量小文件(固定内容+自身 sha256);写/删 → red kind integrity | 勒索加密 profile/凭据面的最早触发(N3 破坏签名兜底) | 范围仅限 ~/.dsh(拍板);读不报警 | | N7 确认拦截(0.1.14) | 破坏确认后对破坏类 fs 操作做包装器级拦截(族 1/2)+ 族 3/4 可选升级拦截;护栏:官方归因/无主操作/vet 自身 IO 永不拦、凭据精确文件级匹配、判定 fail-open | 族 1:确认(N3 勒索组合/完整性金丝雀写删/N4 金丝雀泄漏)后该插件破坏类 fs 操作(write/unlink/rename/cp/truncate/createWriteStream)抛错;族 2:凭据本体删除+覆盖已存在文件单次即时拦截(精确文件:~/.ssh/id_*、~/.dsh/.credentials.yaml、~/.aws/credentials、.pgpass、.netrc、.git-credentials、.npmrc);族 3/4:黄 persistence-write/install-write 报警(默认永不拦) | 黑名单为进程内存(重启清);配置变更需重启;可逆写(appendFile、新建文件)永不拦;族 3/4 仅显式覆写 block 才拦 | | N6 版本行为差分(0.1.15) | 每次自动扫描把 N1 能力清单按 name@version 记入本地 ~/.dsh/vet/capabilities.json(0600,LRU 保留 1000 个版本);升级时与上一记录版本(按 recordedAt 选取,不解析 semver)做清单差分 | 相对上一版的新增能力 → 黄 upgrade-diff(新增网络主机/敏感路径/子进程/依赖/网络或执行能力);新增构成高敏感组合(执行+网络 / 敏感路径+网络 / 敏感路径+执行)→ 红;冷启动(首次安装)只记录,exec+network 双高给黄 upgrade-cold 提示;能力收窄只记录不报警;vet_diff 工具输出本地历史 + 最近两版行为 changelog | 只对比"声明"清单(运行时隐藏/依赖携带的能力变化由 N1 隐能力 + N2 解码覆盖,不在清单差分内);"上一个版本"= 本机实际扫过的最近版本;同版本重装不差分(同版本内容篡改由 content-baseline 哈希覆盖);纯本地、alarm-only | | 取证模式(0.1.21,P0-2) | N4 金丝雀确认后,被确认恶意插件后续每次 fs/子进程/网络操作追加写入 ~/.dsh/vet/forensics/<plugin>-<ts>.jsonl(0600/0700,fail-open) | 完整微活动时间线:"平时不打扰,确认有鬼布天罗地网" | 武装集在内存(重启清除);不落会话内容(仅操作形状+目标,与 N3 同数据面);取证是增强、永不拦截 | | 盾牌 | 浏览器 conversation.session.header.actions + /vet/status.json | 绿/黄/红灯 + 报警计数 | 需 dsh web 重启激活 |

明确不检测(实测验证)

| 形态 | 实测结果 | |---|---| | 间接引用:别名函数 const f = Function; f(...)process["getBuiltinModule"]globalThis.process、间接 eval (0, eval) | 仅 R6 info 或零 finding,verdict=clean | | 运行时/外部构造载荷:base64 串、hex/charCode 拼装、网络/环境变量/参数读码、自修改代码 | base64 构造器串实测零 finding0.1.15(N5/R15):网络 sink 的目标参数静态不可解 → 报 info("刻意遮蔽"——运行时目标无法从源码审计) | | 非源码文件:.jsx/`.tsx`/`.vue`/`.json`/二进制/wasm | 不在扫描面;shell/PowerShell/batch 脚本(.sh/.bash/.ps1/.cmd/.bat)由 R14 覆盖(下载即执行) | | 依赖链/供应链:import/require 图、依赖版本漏洞、package.json scripts/install 钩子、许可证、作者信誉 | 不解析 | | 运行时行为:网络外传、动态原型污染链、死循环/资源耗尽、时序、权限滥用 | 无数据流/行为分析;静态的 <内置>.prototype 覆盖赋值已由 R4 检出(round-7) | | 语义知识:插件实际注入的服务、bundler polyfill 中的 process、遮蔽判定边界 | R5 只认 4 个变量名;遮蔽检查是 v1 启发式(偏少报) | | 宿主工具包的合法 process 使用(process.env 读配置、process.stdin/stdout 协议、process.execPath spawn) | 已解决:targetKind 分级——非 DSH 插件包/官方包(generic)下 R3/R2/R10/R9 死循环降级为能力触达面/提示(info/medium),不进 verdict;DSH 插件包保持严格。round-7 新增形态降级:应用型包(package.json 声明 bin)与 bin 入口文件同样按能力触达面降级;round-7.1 只读成员分类:cwd/env/platform/pid 等纯只读成员在 plugin 模式也降 info(bridges 类无 bin 的 MCP/工具插件不再误伤),kill/exit 等副作用/逃逸成员保持 high/critical。实测 195 官方包全 clean |

0.1.16 加固批次(代码审查产出)

全面代码审查(三路深挖 + 人工实证验证)后的修复(C1–C4 严重,M5–M9 中/低,规则补丁;ENGINE static-v12):

  • C1 — 宿主侧改为单文件 bundle 发布(lib/index.bundle.js),files 白名单不再携带 guard 内部模块 (setRootIndexing/withVetSelfIo/confirmBlock/canaryStore/capabilityDiff 全部闭包封闭)—— 恶意插件再也无法经绝对路径 require 关掉 T2/N7/N4/N1(此前实证可达:全进程致盲、N7 关闭、金丝雀清空)。
  • C2 — ESM 具名导入(import { readFileSync } from 'node:fs')按 Node 互操作快照绕过全部 T2 钩子(实证)。 N1 清单新增 esmNamedBuiltins 标记,runtimeGuard: watch 下对这类插件记录黄色 esm-guard-coverage—— 覆盖盲区显式可见,不再静默(运行时防线剩 T1 哨兵与审计协议,文档边界)。
  • C3DSH_PLUGIN_VET_CACHE_DIR/DSH_PLUGIN_VET_BASELINE_DIR 改为模块加载时快照;进程内改 env 无法再重定向存储/缓存。scanner 缓存读取时校验宿主注入的进程内随机 nonce——预写伪造 clean 缓存条目 (已实证的攻法)失效。
  • C4 — 检测 Error.prepareStackTrace/stackTraceLimit 篡改:归因不可信 → 敏感操作报 red attribution-tampered,且 N7 族 2 凭据破坏经哨兵身份照样拦截(此前 hint 缺失会绕开唯一拦截)。
  • M5 — T2 补 symlink/link/chmod/chown/mkdir/mkdtemp/utimes/lutimes(+Sync) 写面与 lstat/lstatSync 侦察面。
  • M6/M7/M8/M9 — R9 fork-bomb 覆盖 sync 变体 · 能力/基线存储自检外部改写(vet-store-tamper 黄灯)· isSensitiveFsPath 段级匹配(不再子串误抬)· 侧车终止前核对 /proc/<pid>/cmdline(PID 复用防误杀)。
  • 规则补丁 — R2 全局/间接 eval 形态 + require 拼接折叠、R3 globalThis.process.* 成员口径、 R4 Reflect.defineProperty、R9 转义括号组深度、R10 prepare 钩子、R14 python/ruby/perl 下载即执行、 R15 undici sink(见静态规则表)。
  • 会话日志轮换降噪isSessionLogFile 现也识别分片会话文件(session.jsonl.zstd.<shard>);~/.dsh/sessions/**未归因的会话日志删除由 red fs-destroy 降为 yellow(宿主自身运维不可能"攻击自己"),归因到插件的删除仍保持 red(可能是在销毁证据)。

信任边界

  1. verdict 只由确定性静态层产出——规则是正则/AST 判定,不可被提示注入欺骗。
  2. 静态层与插件代码物理隔离——scanner 是独立进程,AST 只读、从不 eval。
  3. 审查走 agent 协议——agent 按 vet-audit-protocol 技能步骤复核(静态判据先行,敏感点逐条深挖),verdict 不受审查环节影响。
  4. 不合成单一总分——禁止把 verdict 与主观评估合并,防止污染 verdict 边界。
  5. 本产品不是安全边界——定位是"减速带+取证层"(具体可绕过形态见下方 Known Limitations 1,与 DSH 官方立场对齐)。
  6. fail-open 起步——默认 mode: reportdeny 由部署者显式开启。
  7. alarm-only——运行时守卫只 watch 不 kill;vet 的自动行为(deny 拦截)仅存在于部署者显式开启的 opt-in 模式。报警只附建议,处置永远留给用户在 DSH 上操作。

Known Limitations

  1. 静态扫描不是安全边界:混淆/编码/动态生成代码可绕过 AST 规则;R6 只提供"疑似"信号。 1b. 源码枚举限制:internal/plugin 自动扫描只递归收集 ≤6 层深、非隐藏(非 . 开头)的 .js/.ts/.mjs/.cjs 文件——深层或隐藏目录里的源码静默不扫(无提示);需要全量时可手动用 scan_plugin(target=package) 扫整个目录。
  2. agent 审查可被提示注入:verdict 永不来自审查环节,但 agent 可能漏报——置信度字段让用户知晓。
  3. internal/plugin 守卫不覆盖运行时动态挂载逃逸:vm 路径由 tools/execute 守卫在调用层拦截。
  4. R5 仅 code 场景:files 场景的 ctx 访问默认不报(误报率高)。
  5. 扫描耗时:大插件包可能超时跳过(R8 info);agent 审查按 vet-audit-protocol 步骤进行。
  6. verdict 是静态层确定性判定;agent 的主观判断记录在健康档案里,不构成安全保证。
  7. /vet/status.json 无鉴权:盾牌轮询需要匿名 GET,路由本身不鉴权——若 dsh web 绑定非回环地址,局域网内可读扫描结论/报警目标。vet 是 alarm-only 观测器,不做越权的访问控制;介意就保持回环绑定或信任网络(POST 开关守卫已有同源校验,无 Origin 拒绝)。
  8. @deepseek-ai/* 内容哈希基线(P-5):对官方包计算内容哈希(SHA-256),与基线比对,防止包名伪造。首次见到自动落盘基线并信任;后续哈希不一致时撤销豁免并记录 red 报警。基线存储支持多版本共存(key = name@version),资源限制(1000 文件 / 50MB / 10s 超时)防 DoS。已知限制:基线文件存储在 ~/.dsh/vet/baseline.json(0600 权限),若攻击者已拿到用户权限可篡改基线文件;多进程并发写可能导致记录丢失(下次扫描重新计算)。可通过 contentBaseline: false 关闭。
  9. R10 已知漏洞核对:直接依赖 OSV 查询(默认开启,osvCheck: false 关闭)+ 传递依赖 upstream-radar 扫描(默认关闭,transitiveDeps: true 开启)。OSV 查询把「包名+精确版本」发到 api.osv.dev;网络失败/超时静默降级。传递依赖扫描需要安装 upstream-radar(本地探测,不使用 npx),未安装时静默降级。OSV-T 规则 severity 为 medium(传递依赖利用面小于直接依赖)。
  10. R11 只认 fs.* 形态:解构/别名调用(const { unlinkSync } = require('fs'))与运行时路径漏检(已实测记录,属静态边界)。
  11. T1/T2 是"防盗摄像头"不是"保险柜":抓明显搞事(内存/fork 炸弹、敏感路径操作、第三方 spawn、网络出口),抓不了 worker 线程/原生插件/低流量慢外联;T2 对 ESM 具名导入快照、process.binding 等旁路不覆盖(0.1.16:N1 新增 esmNamedBuiltins 标记 + esm-guard-coverage 黄灯提示,盲区显式化;归因篡改走 attribution-tampered red)。网络出口观测networkEgress: true,默认开启):包装 http/https/net/http2/tls/dgram/fetch 模块,观测敏感主机/端口。已知限制:IP 直连绕过域名敏感列表;WebSocket 使用底层 net.Socket 会被捕获,但浏览器 WebSocket 不在观测范围;不观测 DNS 查询(性能开销大)。
  12. T2 归因与降噪:栈归因是 best-effort(共享服务/定时器跨插件会误归因);官方包 spawn 默认不报警(能力授权)。
  13. 盾牌激活需要 dsh web 重启:client-modules 在启动时扫描 dsh.client 声明;重启前浏览器不会加载盾牌,但 /vet/status.json 端点与运行时守卫(宿主侧)重启即生效。
  14. 运行时守卫默认关闭runtimeGuard: 'off'):包装 fs/child_process 有性能与稳定代价,opt-in 开启。
  15. process.kill 保持 high(有意设计,round-7.1):kill 是副作用成员,不随只读成员降级——但 MCP/桥接器类插件 kill 自己 spawn 的子进程是正常功能面(dsh-bridges 实测:98/134 条已清,剩余 high 全为 run.js/util.js 的 process.kill)。静态区分 process.kill(child.pid)(pid 来自本包 spawn 返回值)与任意 pid 需要数据流分析,成本高收益低——维持现状,由 agent 按 vet-audit-protocol 审计时人工排除(结论记入健康档案)。
  16. 平台支持(Linux 优先,非 Linux 优雅降级):静态扫描层(scanner-bin/scan_plugin/R1-R12/OSV)、T2 运行时钩子、蜜罐、GUI 盾牌、审计协议均为纯 JS,跨平台(macOS/Windows 可跑)。T1 哨兵是 Linux 专有——依赖 /proc 读 VmRSS/子进程/fd;0.1.21(P0-6)起在非 Linux 上通过显式平台门整体跳过(不拉哨兵、零 respawn/sentinel-down 噪音),指标面板回退 -1/0(不报错,设计如此)。T2 敏感路径按"路径段名"匹配(反斜杠已归一化,Windows 下 .ssh/.env/credentials 等段名同样命中),但"系统根前缀"(/etc /usr /var)是 POSIX 形态——Windows 上写删 C:\Windows\System32 类路径不受系统根判定(段名/密钥特征判定仍有效);macOS 有 /etc /usr /var,T2 全功能。与 DSH 当前 Linux 优先的适配状态一致。

开发

npm run build       # scanner-bin + src 编译到 lib/ + client bundle
npm run typecheck   # tsc --noEmit 全量
npm test            # 构建 + vitest(633 用例全绿)
npx vitest run --coverage   # 覆盖率报告(lines/functions >= 70%,branches >= 50%)

目录:scanner-bin/ 静态引擎(独立进程);src/ 插件本体(tools/guards/audit/report/guard); src/client/ GUI 盾牌;test/ fixtures + 单测 + 对抗矩阵。架构见 docs/ARCHITECTURE.md

许可证

MIT