远程控制dsh
31.1/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/11/3 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add MoonlitDropOfBlood/dsh-remote-control该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · other
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(unknown · 2026/10/27) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
🔴 安全扫描发现高危能力自动 · 静态分析源码
v2.7.0🔴 扫描:高危尚无人工评估
静态扫描发现安装期即执行代码,或命令参数由运行时变量拼接(参数来源无法静态判定,从严处理)。
命令参数由运行时变量拼接读写/删除本地文件发起外部网络请求
查看扫描证据(共 96 处,展示前 77 条)
- 读取本地文件app/live-order-node-test.mjs:93
const linkSource = readFileSync(new URL('./entry/src/main/ets/model/link.ets', import.meta.url), 'utf8'); - 读取本地文件app/live-order-node-test.mjs:97
const storeSource = readFileSync(new URL('./entry/src/main/ets/model/sessionstore.ets', import.meta.url), 'utf8'); - 读取本地文件app/session-detail-contract-test.mjs:5
const page = readFileSync(new URL('./entry/src/main/ets/pages/SessionDetailPage.ets', import.meta.url), 'utf8'); - 读取本地文件app/session-detail-contract-test.mjs:6
const store = readFileSync(new URL('./entry/src/main/ets/model/sessionstore.ets', import.meta.url), 'utf8'); - 读取本地文件app/session-detail-contract-test.mjs:7
const link = readFileSync(new URL('./entry/src/main/ets/model/link.ets', import.meta.url), 'utf8'); - 读取本地文件app/session-detail-contract-test.mjs:8
const protocol = readFileSync(new URL('./entry/src/main/ets/model/protocol.ets', import.meta.url), 'utf8'); - 读取本地文件e2e/auto-test.mjs:43
readFileSync(join(process.env.DSH_HOME ?? join(homedir(), ".dsh"), "remote-control", "config.json"), "utf8"), - 发起网络请求e2e/auto-test.mjs:138
const caps = await client.request("session.capabilities", {}, 5000); - 发起网络请求e2e/auto-test.mjs:145
const created = await client.request( - 发起网络请求e2e/auto-test.mjs:155
await client.request("session.prompt", { sessionId: sid, text: "hello" }, 5000); - 发起网络请求e2e/auto-test.mjs:174
const hist = await client.request("session.history", { sessionId: sid }, 5000); - 发起网络请求e2e/auto-test.mjs:192
await client.request("session.create", { agentPreset: "no-such-preset" }, 5000); - 发起网络请求e2e/auto-test.mjs:211
const withModel = await client.request( - 删除本地文件e2e/auto-test.mjs:438
unlinkSync(epochFile); - 执行外部命令来自配置/变量e2e/auto-test.mjs:462
const child = spawn(process.execPath, [RELAY_SERVER], { - 读取本地文件e2e/deliver-queue-probe.mjs:11
readFileSync(join(process.env.DSH_HOME ?? join(homedir(), ".dsh"), "remote-control", "config.json"), "utf8"), - 发起网络请求e2e/deliver-queue-probe.mjs:35
const hello = await link.request("hello", { proto: 1, clientName: "deliver-probe", appVersion: "1.0.0" }, 15000); - 发起网络请求e2e/deliver-queue-probe.mjs:38
const list = await link.request("session.list", {}, 15000); - 发起网络请求e2e/deliver-queue-probe.mjs:49
const page = await link.request("session.history", { sessionId: target.sessionId, maxMessages: 40 }, 30000); - 发起网络请求e2e/deliver-queue-probe.mjs:69
await link.request("session.prompt", { - 读取本地文件e2e/history-test.mjs:13
readFileSync(join(process.env.DSH_HOME ?? join(homedir(), ".dsh"), "remote-control", "config.json"), "utf8"), - 发起网络请求e2e/history-test.mjs:55
const hello = await link.request("hello", { proto: 1, clientName: "history-test", appVersion: "1.0.0" }, 15000); - 发起网络请求e2e/history-test.mjs:60
const list = await link.request("session.list", {}, 15000); - 发起网络请求e2e/history-test.mjs:84
const v = await link.request("session.history", { sessionId: s.sessionId, maxMessages: 10 }, 30000); - 发起网络请求e2e/history-test.mjs:113
const v2 = await link.request("session.history", - 发起网络请求e2e/link.mjs:456
return this.corr.request((m) => this.send(m), type, payload, timeoutMs); - 发起网络请求e2e/link.mjs:596
return this.corr.request((m) => this.send(m), type, payload, timeoutMs); - 发起网络请求e2e/mock-phone.mjs:36
.request("hello", { proto: 1, clientName: "mock-phone", appVersion: "1.0.0" }) - 发起网络请求e2e/mock-phone.mjs:48
console.log(JSON.stringify(await link.request("session.list", {}), null, 2)); - 发起网络请求e2e/mock-phone.mjs:51
console.log(JSON.stringify(await link.request("session.create", { title: rest.join(" ") || undefined }))); - 发起网络请求e2e/mock-phone.mjs:55
console.log(JSON.stringify(await link.request("session.prompt", { sessionId, text: rest.join(" ") }))); - 发起网络请求e2e/mock-phone.mjs:59
console.log(JSON.stringify(await link.request("session.cancel", { sessionId: rest[0] }))); - 发起网络请求e2e/mock-phone.mjs:63
console.log(JSON.stringify(await link.request("approval.answer", { askId, decision }, 5000))); - 读取本地文件e2e/protocol.mjs:164
const raw = readFileSync(this.#file, "utf8"); - 写入本地文件e2e/protocol.mjs:178
writeFileSync(this.#file, JSON.stringify(this.#data), "utf8"); - 读取本地文件e2e/subagents-test.mjs:20
const cfg = JSON.parse(readFileSync(configPath, "utf8")); - 发起网络请求e2e/subagents-test.mjs:40
const list = await link.request("session.list", {}, 15000); - 发起网络请求e2e/subagents-test.mjs:52
const cat = await link.request("session.subagents", { sessionId: parent }, 20000); - 发起网络请求e2e/subagents-test.mjs:70
.request("session.subagentPrompt", { - 发起网络请求e2e/subagents-test.mjs:86
.request("session.subagentCancel", { - 读取本地文件market/generate-index.mjs:25
const pluginPkg = JSON.parse(readFileSync(join(here, "..", "plugin", "package.json"), "utf8")); - 请求外部主机registry.npmjs.orgmarket/generate-index.mjs:31
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name).replace("%40", "@")}`, { - 发起网络请求market/generate-index.mjs:31
const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name).replace("%40", "@")}`, { - 执行外部命令运行时拼接market/generate-index.mjs:46
const out = execSync(`git log -1 --format=%ct "v${version}" 2>/dev/null || git log -1 --format=%ct`, { encoding: "utf8" }); - 读取本地文件market/generate-index.mjs:148
const disk = readFileSync(outPath, "utf8"); - 写入本地文件market/generate-index.mjs:155
writeFileSync(outPath, json); - 读取本地文件market/sync-into-plugin.mjs:24
const src = readFileSync(SRC, "utf8"); - 读取本地文件market/sync-into-plugin.mjs:29
disk = readFileSync(DST, "utf8"); - 写入本地文件market/sync-into-plugin.mjs:40
mkdirSync(DST_DIR, { recursive: true }); - 写入本地文件market/sync-into-plugin.mjs:41
writeFileSync(DST, src); - 读取本地文件plugin/lib/config.mjs:155
raw = JSON.parse(readFileSync(path, "utf8")); - 写入本地文件plugin/lib/config.mjs:161
renameSync(path, path + ".corrupt-" + Date.now()); - 写入本地文件plugin/lib/config.mjs:197
mkdirSync(dirname(path), { recursive: true }); - 写入本地文件plugin/lib/config.mjs:201
writeFileSync(tmp, JSON.stringify(out, null, 2), "utf8"); - 写入本地文件plugin/lib/config.mjs:202
renameSync(tmp, path); - 读取本地文件plugin/lib/config.mjs:212
const raw = JSON.parse(readFileSync(configFile(), "utf8")); - 读取本地文件plugin/lib/config.mjs:225
const raw = JSON.parse(readFileSync(configFile(), "utf8")); - 读取本地文件plugin/lib/config.mjs:237
const raw = JSON.parse(readFileSync(path, "utf8")); - 写入本地文件plugin/lib/config.mjs:240
mkdirSync(dirname(path), { recursive: true }); - 写入本地文件plugin/lib/config.mjs:242
writeFileSync(tmp, JSON.stringify(raw, null, 2), "utf8"); - 读取本地文件plugin/lib/host-bridge.mjs:372
const bytes = readFileSync(path); - 写入本地文件plugin/lib/host-bridge.mjs:909
: (p) => mkdir(p, { recursive: true }); - 读取本地文件plugin/lib/host-bridge.mjs:1525
const bytes = await readFile(path); - 写入本地文件plugin/lib/host-bridge.mjs:2249
await this.#mkdir(cwd); - 写入本地文件plugin/lib/pairing.mjs:128
mkdirSync(dataDir(), { recursive: true }); - 写入本地文件plugin/lib/pairing.mjs:130
writeFileSync(tmp, svg, "utf8"); - 删除本地文件plugin/lib/pairing.mjs:134
unlinkSync(path); - 写入本地文件plugin/lib/pairing.mjs:138
renameSync(tmp, path); - 删除本地文件plugin/lib/pairing.mjs:146
unlinkSync(path); - 执行外部命令固定命令plugin/lib/pairing.mjs:166
child = spawn("cmd /c start \"\" " + quoted, { shell: true, detached: true, stdio: "ignore", windowsHide: true }); - 执行外部命令固定命令plugin/lib/pairing.mjs:168
child = spawn("open " + quoted, { shell: true, detached: true, stdio: "ignore" }); - 执行外部命令固定命令plugin/lib/pairing.mjs:170
child = spawn("xdg-open " + quoted, { shell: true, detached: true, stdio: "ignore" }); - 发起网络请求plugin/lib/push.mjs:55
return await fetch(url, { ...init, signal: ac.signal }); - 读取本地文件plugin/lib/relay-supervisor.mjs:60
if (existsSync(c)) return c; - 读取本地文件plugin/lib/relay-supervisor.mjs:336
if (this.entry === "" || !existsSync(this.entry)) { - 读取本地文件relay/server.js:125
cert = readFileSync(rawCert); - 读取本地文件relay/server.js:130
key = readFileSync(rawKey);
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库
涉及外部主机:registry.npmjs.org
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
README
由 DeepSeek 最新模型翻译生成dsh-remote-control
用 HarmonyOS 手机远程控制 DeepSeek Harness (DSH):会话遥控、审批/提问应答、任务通知。
┌─ DSH 插件 (PC) ──────┐ WSS ┌─ 中继 (自选部署) ──┐ WSS ┌─ HarmonyOS App ─┐ │ 会话 / 审批桥接 │────────▶│ 只转发密文 │◀────────│ 遥控器 UI │ │ 端到端加密 │ 出站 └──────────────────┘ 出站 └─────────────────┘ └──────┬───────────────┘
└── (可选) Push Kit 通知 ──────────────────────────────▶ 📱
- 两端都以 WebSocket 客户端出站连接中继:中继放局域网 PC 或任一 VPS,手机在局域网或公网都能连;中继只转发 AES-256-GCM 密文,被攻破也读不到内容(协议见 docs/PROTOCOL.md)。
- 零公网部署模式:中继直接跑在 PC 上,手机连 ws://<PC-IP>:<端口> 即可(同一 Wi-Fi)。
- fail-open 安全设计:手机永远不是任务的单点阻塞——超时/断线一律放行给桌面答案器。
展开完整文档(README 剩余 1 节)
dsh-remote-control 用 HarmonyOS 手机远程控制 DeepSeek Harness (DSH):会话遥控、审批/提问应答、任务通知。 ┌─ DSH 插件 (PC) ──────┐ WSS ┌─ 中继 (自选部署) ──┐ WSS ┌─ HarmonyOS App ─┐ │ 会话 / 审批桥接 │────────▶│ 只转发密文 │◀────────│ 遥控器 UI │ │ 端到端加密 │ 出站 └──────────────────┘ 出站 └─────────────────┘ └──────┬───────────────┘ └── (可选) Push Kit 通知 ──────────────────────────────▶ 📱 - 两端都以 WebSocket 客户端出站连接中继:中继放局域网 PC 或任一 VPS,手机在局域网或公网都能连;中继只转发 AES-256-GCM 密文,被攻破也读不到内容(协议见 docs/PROTOCOL.md)。 - 零公网部署模式:中继直接跑在 PC 上,手机连 ws://<PC-IP>:<端口> 即可(同一 Wi-Fi)。 - fail-open 安全设计:手机永远不是任务的单点阻塞——超时/断线一律放行给桌面答案器。 功能 | 能力 | 说明 | | 会话遥控 | 会话列表(实时状态)/ 新建 / 发送提示词 / 流式查看回复 / 取消任务 | | 审批 · 提问应答 | 智能体请求审批或用户提问时手机上直接允许 / 拒绝 / 回答(带倒计时) | | 任务通知 | 华为 Push Kit 推送(可选;未配置时优雅降级) | 仓库结构 | 目录 | 内容 | 技术栈 | | plugin/ | DSH 插件(Host 侧半边),安装进 DSH 配置档 | Node.js / Cordis | | relay/ | 中继服务器(哑管道,只转发密文帧) | Node.js + ws | | app/ | HarmonyOS 手机 App(DevEco 工程) | ArkTS / ArkUI | | e2e/ | 协议参考实现 + mock 手机/DSH + 自动化联调 | Node.js | | docs/PROTOCOL.md | 线协议契约 v1.0.2(三方共同合同) | — | 快速开始 1. 起中继(局域网:跑在 PC 上即可) cd relay && npm install && node server.js # 默认 0.0.0.0:8787 2. 安装 DSH 插件(link 安装) dsh plugin add ./plugin # 或 DSH 的 plugin_manager install_bundle 3. 配对(推荐扫码) DSH 会话里发送 /remote-pairing → PC 屏幕显示配对二维码手机 App 配对页点「扫码配对」→ 自动填参并连接(手动输入兜底:config.json 的 channel/secret + relayUrl 三项照填) App 侧构建与装机见 app/README.md;mock 联调(无真机/无 DSH)见 e2e/README.md。 安全模型 - 配对 secret 经 HKDF-SHA256 派生端到端密钥;每帧 AES-256-GCM(iv||ct||tag),AAD 绑定发送方 role 与 seq 防串帧。 - 中继只见密文;channel 是随机能力串;hello 用 HMAC 签名证明持有 secret。 - 启动即跑协议 KAT 自测(docs/PROTOCOL.md §7),失败即禁用连接,绝不带病上线。 - 审批拦截 fail-open:超时(默认 120s)/出错/断线 → 放行桌面答案器。 License MIT
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
MoonlitDropOfBlood/dsh-remote-control
远程控制dsh
相关插件 · 其他
模型破甲清洗HunYiSage/dsh-purge
⚔️ DeepSeek Harness 网络安全红队工具dsh-purge
★ 16,993已汉化DeepSeek 客户端
73
女娲蒸馏alchaincyf/nuwa-skill
输入名人名字,提炼其思维模型与决策方式供你调用
★ 37,308已汉化DSH
72
逆向分析桥接Fanqi89/dsh-rea
REA(Reverse Engineer Anything)MCP 桥接,用来把 REA 逆向工具接入 DSH 插件
★ 51已汉化DSH
72
语音女友beiyege-01/dsh-voice-ai-girlfriend
语音 AI 女友Voice AI girlfriend for DeepSeek Harness:Whisper…
★ 888已汉化DSH
71.6
红队越狱测试套件Minglink/dsh-infinite-gen-5
DeepSeek v4.1 flash 逆向工具无限五代 求 Star 收藏 ⭐欢迎大家提交项目的改进
★ 3,759已汉化DSH
71.4
协同办公空间dream-num/univer-workspace
一个让人类与 AI Agent 共同创作、协作和审阅的开源 Office 工作空间。
★ 2,269已汉化DSH
70.8
这是你的仓库?认领条目