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

@lixiangzhong/dsh-shell-secrets

v0.1.1

Published

DSH bundle: re-inject KEY/PASSWORD/SECRET/TOKEN variables from the launching environment into dsh bash subprocesses under their original names

Readme

@lixiangzhong/dsh-shell-secrets

npm version license

一个 dsh(DeepSeek Harness)插件:把启动 dsh 时环境里 名字匹配 KEY / PASSWORD / SECRET / TOKEN 的变量,以原始变量名注入 bash 工具的子进程。

export GITHUB_TOKEN=ghp_xxx PGPASSWORD=secret
dsh web

之后模型通过 bash 工具执行命令时,gh、psql、aws、curl 这类自己读环境变量的 CLI 无需改写:

gh auth status              # 直接读 $GITHUB_TOKEN
psql -h db -U app           # 直接读 $PGPASSWORD

⚠️ 安全须知

这个插件有意绕过 dsh 的凭证隔离机制。启用之后,匹配到的变量会进入每一个 bash 子进程 —— 包括 npm install 的 postinstall 脚本,以及模型运行的任意第三方二进制。

只要模型执行 env,这些值就会出现在工具结果里,也就是会话日志与模型上下文里。插件无法对 输出做脱敏,也无法撤回已经写进日志的值。

建议:

  • 只在受信的 workspace 和会话里使用;
  • 验证时只列变量名,不要打印值:env | cut -d= -f1 | grep -E '_TOKEN$|PASSWORD$|_KEY$';
  • 一旦有值进了日志又不想留,直接轮换该密钥。

为什么需要它

dsh 在启动子进程前会做一次固定的凭证清理:名字匹配 /KEY|PASSWORD|SECRET|TOKEN/i 的变量、 以及所有 DSH_*,都不会传给 bash 子进程。因此即使用户在自己的 shell 里 export GITHUB_TOKEN=..., 模型执行的命令里也读不到它。

dsh 官方提供的插件接缝 ctx.shellEnv 只能注册 DSH_* 前缀的变量,命令里得写成 $DSH_GITHUB_TOKEN,对 gh、psql 这类直接读 GITHUB_TOKEN / PGPASSWORD 的 CLI 没用。

本插件改为接管 shell 执行器,把同一批变量以原始名字放回子进程环境 —— 走的仍是 dsh 文档化的落点(ShellExecSpec.env,语义是"在凭证清理之后合并")。

安装

环境要求:已安装 dsh CLI(本插件在 dsh 进程内运行,Node 版本要求 ≥ 22);用 dsh plugin 管理插件时需要 pnpm(dsh 自身用 pnpm 管理 profile 依赖)。

从 npm 安装(推荐)

dsh plugin --profile web add @lixiangzhong/dsh-shell-secrets

dsh plugin 会把包装进 ~/.dsh/profiles/<profile>/node_modules,并把包名追加到 dsh.profile.bundles 层(因为包里声明了 dsh.bundle.patch),不需要手改任何 YAML。

--profile 按需替换(web / tui / headless …)。装好后重启 dsh 才会生效。

从源码或离线 tarball 安装

# 目录形式
dsh plugin --profile web add file:/path/to/dsh-shell-secrets

# tarball 形式(npm pack 产物)
dsh plugin --profile web add file:./lixiangzhong-dsh-shell-secrets-0.1.0.tgz

本地安装必须使用 file:(会落成真实目录),不要用 link::软链会让 Node 按真实路径去 源码目录解析 dsh 自身的包,从而加载到两份 harness 模块实例,服务注册会出问题。

升级与卸载

dsh plugin --profile web update @lixiangzhong/dsh-shell-secrets    # 升级到最新版
dsh plugin --profile web add @lixiangzhong/[email protected] # 或指定版本
dsh plugin --profile web remove @lixiangzhong/dsh-shell-secrets    # 卸载(依赖 + bundle 层一起移除)

升级/卸载后同样需要重启 dsh。

生效时机

| 改动 | 生效方式 | | --- | --- | | 启动环境里的密钥变量 | 重启 dsh | | DSH_SHELL_SECRETS_* 配置 | 重启 dsh | | 插件版本(安装 / 升级 / 卸载) | 重启 dsh |

变量与配置都来自 dsh 启动时的那个环境,进程启动后不再变化。

配置

全部通过环境变量(在启动 dsh 之前设置):

| 变量 | 默认 | 说明 | | --- | --- | --- | | DSH_SHELL_SECRETS_PATTERN | KEY\|PASSWORD\|SECRET\|TOKEN(忽略大小写) | 自定义匹配正则。默认值与 dsh 自身的凭证清理规则一致,保证"被清掉的正好被补回来" | | DSH_SHELL_SECRETS_INCLUDE | 空 | 逗号分隔的 glob(* / ?),优先于 PATTERN,例如 *_TOKEN,AWS_* | | DSH_SHELL_SECRETS_EXCLUDE | 空 | 逗号分隔的 glob 排除项,例如 MONKEY,KEYBOARD_*(修掉子串误伤) | | DSH_SHELL_SECRETS_MAX_BYTES | 8192 | 单个值的长度上限,超长跳过 | | DSH_SHELL_SECRETS_DISABLE | 空 | 设为任意非空值即停用注入(不必卸载插件) |

规则细节:

  • DSH_* 永不注入:保持 dsh "外部传入的 DSH_* 会被丢弃" 的既有约定,避免伪造框架自身的事实。
  • 默认规则是子串匹配,因此 MONKEY、KEYBOARD_LAYOUT 这类名字也会命中 —— 用 EXCLUDE 排除即可。
  • 空值、纯空白、超长值会被跳过;含换行的值仍会注入(保真优先),但会在装载日志里提示。
  • 配置非法(正则写错、上限非正整数)会让插件装载失败并报错:宁可启动时报错,也不要静默不注入。
  • 装载日志只打印变量名与原因,绝不打印值。

快速验证

# 1) 在启动 dsh 的 shell 里设置一个测试变量,然后启动 dsh
export MY_TEST_PASSWORD=probe-ok
dsh web
# 2) 在 dsh 的 bash 工具里执行
echo "${MY_TEST_PASSWORD-unset}"        # → probe-ok(原始名字可用)

# 只列名字,不要打印值
env | cut -d= -f1 | grep -E '_TOKEN$|PASSWORD$|SECRET$|_KEY$' | sort
env | cut -d= -f1 | grep '^DSH_'        # 应只有 DSH_HOME / DSH_SHELL / DSH_SESSION_ID / DSH_WEB_URL

已知限制

  • 只处理 bash 执行器。使用持久 PTY shell 的场景(minimal agent preset、sdk-minimal profile) 走的是另一套 terminals 服务,不在覆盖范围内。
  • Windows 的 pwsh 未覆盖(机制上可同构补充,尚未实现)。
  • 只从启动环境读取,不读文件;dsh 启动之后才 export 的变量不会生效。
  • 变量集合在插件装载时确定一次,运行期不再刷新。

兼容性

本插件通过覆写 shell 执行器实现,因此绑定了 dsh 的内部接口:

  • @deepseek-ai/dsh-bash-sandbox 导出的 SandboxBashExecutor,及其 resolve / run / start 方法;
  • ShellExecSpec.env 的合并语义(在凭证清理之后合并);
  • ctx.shell 服务名与 bash-sandbox 配置行。

为了尽早暴露不兼容,插件装载时会做一次自检,并在 dsh 日志里以 error 级别报告(不阻断启动, 以免误报导致 dsh 起不来):

  • 基类是否仍提供 resolve / run / start;
  • 插件解析到的 harness 包与 dsh 自身使用的是否是同一份(避免 profile 里装出第二份 harness 包)。

已测试环境

| dsh | Node | 平台 | 结果 | | --- | --- | --- | --- | | 0.1.5-rc.1 | 26.x | macOS | 前台与后台任务路径均注入成功,单元测试 13/13 |

其它版本/平台(尤其 Windows)尚未验证,欢迎反馈。dsh 升级后建议确认一次:

echo "${GITHUB_TOKEN-unset}"                                     # 或任一敏感变量
env | cut -d= -f1 | grep -E '_TOKEN$|PASSWORD$|SECRET$|_KEY$'    # 只列名字

常见问题

装了但命令里读不到变量

  1. 变量是在启动 dsh 的那个 shell 里 export 的吗?(.zshrc 里 export 也可以,但要重启 dsh)
  2. 装/改配置之后重启 dsh 了吗?
  3. 用 env | cut -d= -f1 | grep '^DSH_' 之外的方式确认名字是否在注入清单里;装载日志会打印 可注入密钥变量 N 个: ...,若为 0 并伴随警告,说明启动环境里没有匹配项或 PATTERN 写错了。

dsh plugin add 报 ERR_PNPM_UNEXPECTED_STORE

profile 的 node_modules 与当前 pnpm 的大版本不一致(store 版本不同)。两种处理:使用与 profile 一致的 pnpm 版本重建一次(cd ~/.dsh/profiles/<profile> && pnpm install),或者统一 本机的 pnpm 版本。

dsh plugin add 报 404 / 找不到包

使用了企业或国内镜像,而镜像尚未同步新包。显式指定官方 registry:

dsh plugin --profile web add @lixiangzhong/dsh-shell-secrets --registry=https://registry.npmjs.org

误把值打印出来了

无法撤回,请轮换该密钥;后续验证只列名字。

工作原理(简述)

  1. 插件在装载时读一次启动环境,按配置挑出需要注入的变量(纯函数逻辑,见 lib/secrets.js);
  2. 用 SecretsBashExecutor 接管 dsh 的 shell 执行器(覆写 run 与 start 两个方法);
  3. 每次执行前把这些变量并入 ShellExecSpec.env —— 该字段由 dsh 在凭证清理之后合并, 因此原始变量名能进入子进程环境,同时不会覆盖 dsh 自己注入的 DSH_*(那些走另一个字段)。

插件只做"把已有变量放回去",不读文件、不访问网络、不做持久化。

开发

node --test              # 单元测试(纯逻辑,零依赖)
npm pack --dry-run        # 查看发布产物

本地联调:把仓库目录以 file: 方式装进 profile(见上文),改完代码后重新 dsh plugin remove && add 并重启 dsh。仓库内的 deploy.mjs 提供了不依赖 pnpm 的 备用部署方式(拷贝 + 手写挂载行),适用于无法使用 pnpm 的环境。

维护者笔记(本机环境、踩过的坑、发布流程)见 NOTES.md。

许可证

MIT