在一次性容器里试装插件,按 harness 记录判定成败
26.1/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add DshMarketPlace/dsh-plugin-validator该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · market
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 75 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 17 处,展示前 17 条)
- 执行外部命令来自配置/变量preset.mjs:52
execFile(file, args, { timeout: TIMEOUT_MS, maxBuffer: 16 << 20, ...opts }, (error, stdout, stderr) => { - 读取本地文件preset.mjs:97
manifest = JSON.parse(await readFile(join(profile, "package.json"), "utf8")); - 执行外部命令来自配置/变量probe.mjs:32
execFile( - 读取本地文件probe.mjs:89
const extra = diagnostics ? await readFile(diagnostics, "utf8").catch(() => "") : ""; - 读取本地文件probe.mjs:185
manifest = JSON.parse(await readFile(join(profile, "package.json"), "utf8")); - 请求外部主机registry.npmjs.orgprobe.mjs:300
const res = await fetch(`https://registry.npmjs.org/${pkg.replace("/", "%2f")}`, { - 发起网络请求probe.mjs:300
const res = await fetch(`https://registry.npmjs.org/${pkg.replace("/", "%2f")}`, { - 读取本地文件probe.mjs:316
m = JSON.parse(await readFile(join(second.home, "profiles", "web", "package.json"), "utf8")); - 读取本地文件probe.mjs:368
await readFile(join(home, "profiles", "web", "node_modules", pkg, "package.json"), "utf8"), - 请求外部主机registry.npmjs.orgprobe.mjs:375
const res = await fetch(`https://registry.npmjs.org/${pkg.replace("/", "%2f")}`, { - 发起网络请求probe.mjs:375
const res = await fetch(`https://registry.npmjs.org/${pkg.replace("/", "%2f")}`, { - 读取本地文件run.mjs:26
const specs = readFileSync(specPath, "utf8") - 读取本地文件run.mjs:32
existsSync(outPath) - 读取本地文件run.mjs:33
? readFileSync(outPath, "utf8") - 执行外部命令固定命令run.mjs:66
const child = spawn("docker", args, { stdio: ["ignore", "pipe", "pipe"] }); - 写入本地文件run.mjs:92
appendFileSync(outPath, JSON.stringify(result) + "\n"); - 读取本地文件run.mjs:103
for (const line of readFileSync(outPath, "utf8").split("\n").filter(Boolean)) {
扫描于 2026/11/3(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库
涉及外部主机:registry.npmjs.org
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 沙箱试装插件
- 一次性容器隔离
- 按记录判定成败
为 DeepSeek Harness 插件做沙箱安装验证——把每个插件装进一次性容器里的全新配置档,再报告 harness 记录了什么
README
由 DeepSeek 最新模型翻译生成English · 简体中文
把一个 DeepSeek Harness 插件装进一次性容器里的干净 profile,然后报告 harness 自己记下了什么 —— 而不是 CLI 打印了什么。
dshmarketplace.dev 上每条插件的安装结论,就是这个东西跑出来的。
为什么 exit code 不算证据
dsh plugin add 在什么都没装上的时候也返回 0。在一台没有 pnpm 的机器上就是这样:它
把原因打出来,然后告诉你成功了。
所以这里根本不看 exit code。装完之后去读 harness 自己写的 profile manifest —— $DSH_HOME/profiles/web/package.json —— 看 dsh.profile.bundles 里有没有它。在那儿才算装上了,别的都不算。
命令是原样整条传进去的,跟 catalogue 上发布的一模一样。要测的是别人会复制的那条命令,不是我们自己拼出来的版本。
六种结论
其中只有两种是真的坏了。
| 结论 | 含义 | 算不算问题 |
| passed | 装上了,而且注册进了 profile 的 bundles | — |
| not-a-layer | 装是装上了,但它没声明 dsh.bundle,所以是个普通依赖。
展开完整文档(README 剩余 1 节)
English · 简体中文
把一个 DeepSeek Harness 插件装进一次性容器里的干净 profile,然后报告 harness 自己记下了什么 —— 而不是 CLI 打印了什么。
dshmarketplace.dev 上每条插件的安装结论,就是这个东西跑出来的。
为什么 exit code 不算证据
dsh plugin add 在什么都没装上的时候也返回 0。在一台没有 pnpm 的机器上就是这样:它
把原因打出来,然后告诉你成功了。
所以这里根本不看 exit code。装完之后去读 harness 自己写的 profile manifest —— $DSH_HOME/profiles/web/package.json —— 看 dsh.profile.bundles 里有没有它。在那儿才算装上了,别的都不算。
命令是原样整条传进去的,跟 catalogue 上发布的一模一样。要测的是别人会复制的那条命令,不是我们自己拼出来的版本。
六种结论
其中只有两种是真的坏了。
| 结论 | 含义 | 算不算问题 |
| passed | 装上了,而且注册进了 profile 的 bundles | — |
| not-a-layer | 装是装上了,但它没声明 dsh.bundle,所以是个普通依赖。theme、agent bundle、库都落在这里;harness 自己也说了,以后版本补上就会自动生效 | — |
| needs-approval | 解析和落盘都没问题,但 build script 被 pnpm 拦了。加一条 allowBuilds 就能用 | — |
| rejected | 这串东西不是 dsh plugin add 命令,或者目标既不是 npm 包名也不是 github: spec。什么都没跑 | — |
| failed | 装上了但没注册、manifest 根本没写出来,或者 package.json 开头带 UTF-8 BOM | 是 |
| timeout | 超过 180 秒 | 是 |
后两类里有两个是被第一版判错才单独拆出来的。not-a-layer 在 failed 桶里待了一天,把能用的 theme 判成坏的,理由只是它不是同一种包。needs-approval 管的是源码安装时
pnpm 拒绝跑 prepare —— 而源码安装本来就必须干这件事。
429 永远不是结论。 registry 限流的时候 probe 给的是 error,下游不会拿它发布任何东西。这条分支的由来是:曾经有 119 个能用的插件被 npm 限流判成坏的,另外 28 个死在 codeload.github.com 上 —— 源码安装要从 GitHub 拉 tarball,GitHub 同样限流。谁的 429 不重要,它量的永远是我们自己的流量,不是插件。
怎么用
$ docker build -t dsh-validator:latest .
单个插件:
$ docker run --rm dsh-validator:latest "dsh plugin --profile web add @liustack/modlens"
{"status":"passed","detail":"installed and registered in the web profile","bundles":["@liustack/modlens"],"dependencies":["@liustack/modlens"],"blockedBuildScripts":[]}
批量 —— 一行一个 JSON,要 fullName 和 install 两个字段:
$ cat specs.jsonl
{"fullName":"liustack/modlens","install":"dsh plugin --profile web add @liustack/modlens"}
{"fullName":"someone/other","install":"dsh plugin --profile web add github:someone/other"}
$ node run.mjs specs.jsonl results.jsonl 3
2 specs, 0 already done, 2 to run
2/2
{
"passed": 1,
"needs-approval": 1
}
可断点续跑。 结果是跑完一条追加一条,已经有结果的直接跳过,所以跑到第二小时挂掉只赔第二小时,不用从头再来。
| 环境变量 | 默认值 | |
| VALIDATOR_IMAGE | dsh-validator:latest | 用哪个镜像 |
| VALIDATOR_MEMORY | 1500m | 单容器内存和 swap 上限 |
| VALIDATOR_CPUS | 1.0 | 单容器 CPU 上限 |
| PROBE_TIMEOUT_MS | 180000 | 容器内的安装超时 |
默认值是故意压低的:这东西跑在一台还跑着别人服务的机器上,一批校验把别人饿死,比跑一整晚更糟。
隔离
插件的安装步骤是陌生人的代码,所以一个插件一个容器,跑完就销毁。
- --rm,一插件一容器,跑完什么都不留
- --cap-drop ALL 加 --security-opt no-new-privileges
- 用镜像里的非特权 node 用户跑,不是 root
- 不挂载宿主目录 —— 没有出去的路
- 内存、swap、--pids-limit 512 都封顶
- 300 秒的墙钟 kill,比 probe 自己的超时更长,卡死的容器占不住槽位
runner 故意做成文件进、文件出,手上没有任何凭据。一个能摸到数据库 token 的 postinstall 就等于拿到了整个数据库,所以跑不可信安装脚本的那个进程,手上就不该有东西可摸。marketplace 的 nightly job 里这就是单独一个 CI job:一个 job 算出要测哪些,这个 job 负责跑,第三个 job 把结果读回去。
网络是开着的(--network bridge),因为要测的就是"能不能装上"。这是沙箱诚实的边界:它约束的是安装过程在宿主上能碰到什么,不是它能往外发什么。
它测出来的东西
先测出的是我们自己的 bug,不是别人的。 第一次全量跑回来 410 个 failed,里面几乎没有真坏的插件:
- 852 条声明了 npm 包的记录里,412 条是错的 —— 362 条写的包压根没发布过,50 条写的是别人的包。这里面绝大多数是 fork:fork 会原样继承上游的 package.json,于是 fork 的卡片上印的是上游的安装命令。我们装了陌生人的代码,还差点把它的失败挂在 fork 作者名下。
- 另外 119 个是 npm 在限流我们,28 个是 GitHub 在干同样的事。
- 18 个是跑到一半改 probe 弄出来的。
剩下的是个位数百分比,大多是 monorepo 和 workspace 的解析错误 —— 外加一个值得单独点名的: package.json 存成了带 UTF-8 BOM 的,JSON.parse 在哪儿都不认。Windows 上的编辑器是悄悄加的,作者自己根本看不见。所以这条结论会把原因直接说出来,而不是丢进泛泛的 failed 里。
"读代码"已经两次没能发现根本跑不起来的命令,"真去装一遍"两次都发现了。
为什么钉 pnpm 10 而不是 11
镜像里钉 pnpm 10 是有意的。pnpm 11 在 ERR_PNPM_IGNORED_BUILDS 上返回非零,dsh 把这个读成安装失败,于是在写 bundle 那一行之前就停了 —— 同一个插件在 11 上是 needs-approval,在 10 上是 passed。这是包管理器的事实,不是插件的事实;钉住版本才能让结论说的是插件。
镜像用 node:22-bookworm 而不是 -slim,也是同一类原因:@deepseek-ai/dsh 依赖 node-pty,它没有 arm64 预编译产物,npm 只能回落到 node-gyp,于是需要 python 和一套 C++ 工具链。在 slim 上安装会死在 gyp ERR! not ok,看起来像包坏了,其实是缺编译器。
同一个 catalogue 的其他入口
- 网站 —— dshmarketplace.dev
- npm —— npx dshmarketplace-cli find memory
- PyPI —— pip install dshmarketplace
- DSH 里面 —— dsh plugin --profile web add dshmarketplace-plugin
- 油猴脚本 —— DSH Plugin Radar
参与
欢迎提 issue 和 PR,尤其是你觉得判错了的结论。如果是某条记录本身写错了,那属于 marketplace 仓库 —— 数据在那边,不在这里。
联系
- 社区 —— LINUX DO
- 问题反馈 —— GitHub Issues
致谢
- LINUX DO —— DSH 生态实际上是在这里被讨论的,这个项目也在这里发布和收反馈。作者本人在 LINUX DO 发过帖的插件,在目录里会带一个认证标记。
- awesome-dsh-plugin
(CC0-1.0)—— 目录的收录种子来自这里。
授权
MIT。独立项目,与 DeepSeek 官方无关。预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
DshMarketPlace/dsh-plugin-validator
在一次性容器里试装插件,按 harness 记录判定成败
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,025未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,358已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13938 个插件含 PR 收录与…
★ 350已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7
这是你的仓库?认领条目