mcpField
V
vaultshell

vaultshell

本地服务
github.com/SoWhatI安全14 周前更新

关于 vaultshell

vaultshell 是一款 MCP 服务,用于保存密钥引用,并在执行时将解析出的值注入 Shell 进程。它面向通过 AI 工具运行命令的用户,通过输出脱敏避免密钥明文进入模型上下文、工具响应、日志和审计记录。

主要功能

  1. 01按规则向命令注入密钥
  2. 02对命令输出进行脱敏
  3. 03一次性命令与持久 Shell 会话
  4. 04注入凭据的本地反向代理
  5. 05密钥和规则管理工具
  6. 06脱敏审计记录

适用场景

  1. 01运行需要凭据的命令,同时避免模型接触密钥值
  2. 02通过凭据代理发送 API 请求
  3. 03管理密钥注入规则并查看脱敏审计记录

MCP 相关

向 MCP 客户端提供 Shell 执行、会话、代理、密钥、规则和审计工具。密钥值注入子进程,工具输出会经过脱敏。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"sowhati-vaultshell": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/sowhati/vaultshell:0.1.2"
]
}
}
}
启动命令docker run -i --rm ghcr.io/sowhati/vaultshell:0.1.2

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
ocighcr.io/sowhati/vaultshell:0.1.2

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

vaultshell

English | 简体中文

CI npm License: MIT

已收录于官方 MCP Registry:io.github.SoWhatI/vaultshell

一个 MCP 服务,将机密存储在本地安全存储中,根据规则在执行时将其注入 shell 子进程,并确保机密明文永远不会进入模型上下文——不会出现在工具响应、 日志或审计记录中。

闭环方案:基于引用的存储 + 条件注入 + 强制输出脱敏。

状态:M3——单次命令 + 持久会话 + 凭据代理 + 外部 CLI 后端。请参阅 CHANGELOG 和 docs/design-spec.md。

铁律

  • MCP 工具绝不会返回机密明文。响应只包含名称、 掩码([REDACTED:NAME])和脱敏后的输出。
  • 解析器仅在启动器内部调用;值直接进入 子进程的 env,绝不会经过工具层。
  • shell_exec 没有自由格式的 env 参数。机密只能通过规则引用 注入。
  • 脱敏器故障时采用失败关闭策略:丢弃输出,绝不返回原始内容。

快速开始

需要 Node.js 20+。

从 GitHub 安装(无需 npm Registry 账户)
# Run on demand directly from the repo (npm installs devDependencies and
# builds dist/ via the `prepare` script):
npx -y github:SoWhatI/vaultshell

# Or install globally:
npm i -g github:SoWhatI/vaultshell

这与 npm Registry 包含相同代码,通过 git 安装—— npm 会克隆仓库、运行 prepare(→ npm run build),并链接 vaultshell 可执行文件。为确保可复现,请固定标签: npx -y github:SoWhatI/vaultshell#v0.1.1。

Docker(ghcr.io)
docker run -i --rm \
  -e MASTER_KEY=<64 hex chars> \
  -v ~/.vaultshell:/home/node/.vaultshell \
  ghcr.io/sowhati/vaultshell:latest

使用 Docker 的 MCP 客户端配置:

{
  "mcpServers": {
    "vaultshell": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MASTER_KEY=<64 hex chars>",
        "-v", "~/.vaultshell:/home/node/.vaultshell",
        "ghcr.io/sowhati/vaultshell:latest"
      ]
    }
  }
}

镜像以非 root 用户 node 运行(HOME=/home/node),因此数据 卷挂载到 /home/node/.vaultshell。镜像中不包含 node-pty——在 容器中会话会自动回退到管道模式(pty: false);注入和脱敏不变。web 子命令 会透传(docker run … ghcr.io/sowhati/vaultshell web——在容器内使用回环地址, 用途有限)。

不通过 Smithery 分发: Smithery 已转为仅托管模式(只接受部署到其自有基础设施上的服务)。 按设计,vaultshell 的机密必须保留在用户的机器上——第三方托管 与其威胁模型不兼容,因此我们特意不在该平台发布。

从源代码安装
# Run via npx (after publish) or from source:
npm install && npm run build

# 1. Create a master key for the encrypted-file backend
export MASTER_KEY=$(openssl rand -hex 32)

# 2. Create ~/.vaultshell/config.yaml and ~/.vaultshell/rules.yaml
#    (full annotated examples: docs/user-guide.md)

# 3. Store a secret (never echoed back) and run with injection
#    via your MCP client's tools: secret_set, then shell_exec

Claude Desktop(claude_desktop_config.json):

{
  "mcpServers": {
    "vaultshell": {
      "command": "npx",
      "args": ["-y", "vaultshell"],
      "env": { "MASTER_KEY": "<64 hex chars>" }
    }
  }
}

完整设置说明、配置参考、规则编写指南、客户端 集成和常见问题解答:docs/user-guide.md。

MCP 工具

工具用途返回值
shell_exec执行一次性命令,并按规则注入。参数:command、cwd?、profile?、extraEnv?(允许列表)、dryRun?、timeoutSeconds?(≤3600){exitCode, stdout, stderr}(已脱敏)、injected:[names]、ruleId、redactedCount、timedOut、truncated、warnings;dryRun → {dryRun:true, ruleId, injected, envKeys, denied}
shell_session_open打开持久会话;创建时注入一次机密{sessionId, cwd, injected:[names], pty, ttlSeconds}
shell_session_send向会话发送命令{output}(合并后已脱敏)、exitCode、redactedCount
shell_session_close结束会话;进程结束时机密也会消失{ok}
shell_session_list列出活动会话仅元数据
shell_session_revoke结束会话并在不含机密的情况下重新创建{sessionId}(新的)
shell_proxy_start在 127.0.0.1 上启动注入凭据的反向代理{proxyId, port, expiresAt, upstreamHost}
shell_proxy_stop停止代理{ok}
shell_proxy_list列出运行中的代理仅元数据(包括机密的名称,绝不包含值)
secret_list列出名称和元数据(后端引用,可解析)绝不返回值
secret_set写入后端;持久化,绝不回显{name, ok}
secret_delete删除并注销{name, ok}
secret_probe检查引用是否可解析{ok, masked:"****"}
rule_list规则和静态警告(例如 inject-everywhere)—
rule_validate静态检查结果:未知机密、无法触达的规则、inject-everywhere、联合风险、requireConfirm 功能{ok, findings[]}
audit_query读取审计条目仅名称和已脱敏的命令

执行限制(M3)

  • shell_exec 中的 dryRun: true 会报告预期的 ruleId、injected 名称、最终环境变量 键列表(绝不包含值)以及拒绝列表判定结果, 且不会执行任何操作。
  • timeoutSeconds(默认值为 defaults.execTimeoutSeconds = 120,上限为 3600)会终止命令并返回 timedOut: true。
  • defaults.maxOutputBytes(默认值为 1 MiB)会截断每个输出流,并设置 truncated: true。截断发生在 Redactor 处理之后,绝不会绕过脱敏。
  • defaults.maxConcurrentExecs(默认值为 8)会拒绝超出上限的并发 shell_exec 调用,并给出明确错误(不排队)。
  • 以上情况均会记录在审计日志中(dryRun / timedOut / truncated 标记)。

Web 配置 UI

vaultshell web            # loopback-only HTTP UI on a random port
vaultshell web --port 5317

会打印一个一次性令牌 URL,例如 http://127.0.0.1:5317/?token=…——打开它即可管理机密(仅写入)、编辑规则并查看实时静态验证警告和匹配器试运行结果、编辑配置,以及浏览已脱敏的审计日志。令牌会随进程结束而失效;每次 API 调用都需要该令牌,修改操作必须使用同源的 application/json 请求,并且任何端点都绝不会返回机密值。不要进行端口转发。设计和威胁模型: docs/web-config-ui-design.md。

凭据代理(M3)

对于高敏感度 API 令牌,最好完全不要将机密放入环境变量。在 config.yaml 中声明代理:

proxies:
  - id: stripe
    upstreamHost: https://api.stripe.com
    secretRef: STRIPE_KEY                          # registry name or full ref
    headerTemplate: "Authorization: Bearer ${value}"

然后执行 shell_proxy_start { "id": "stripe" } → { port, expiresAt },命令即可调用 http://127.0.0.1:<port>/v1/charges,而不是 https://api.stripe.com/v1/charges。代理仅在内存中注入标头,并会在 TTL 到期后自动停止(默认 300s)。审计记录主机和机密名称,绝不记录标头值。

边界:仅支持 http:// / https:// 上游(代理到上游的 TLS 会经过正确验证;不支持 CONNECT 隧道,也不进行 TLS 终止);客户端到代理这一段在 127.0.0.1 上使用明文,沿用威胁模型中同一 UID 本地进程的边界。

持久会话(M2)

shell_session_open 会启动一个长期运行的 Shell,并在创建时注入匹配规则中的密钥。会话会在空闲 TTL 到期后回收(defaults.sessionTtlSeconds,默认 900s;可通过规则中的 ttlSeconds 或单次调用覆盖)——进程终止时,密钥也会随之消失。shell_session_revoke 会立即终止可能已遭入侵的会话,并重新创建一个不含任何密钥的会话。

会话通过 node-pty 使用真正的 PTY(可选依赖——需要原生构建;macOS 需安装 Xcode CLT,Linux 需安装 build-essential + python3)。如果无法加载或启动 node-pty,vaultshell 会自动回退到普通的 child_process Shell,且 shell_session_open 响应中会显示 pty: false;注入和脱敏行为完全相同,只是交互性会有所降低。会话输出会合并 stdout/stderr(PTY 语义),并经过同一 Redactor 处理。

后端支持矩阵

后端引用方案状态平台备注
加密文件encfile://NAME✅ 已实现所有平台AES-256-GCM;主密钥来自 env:MASTER_KEY 或 macOS 钥匙串;默认
本地钥匙串keychain://svc/acct⚠️ 仅限 macOSmacOS启动 security CLI;Linux/Windows 会给出明确错误
进程环境变量env://NAME✅ 已实现所有平台只读;适用于 CI
文件file://path✅ 已实现所有平台读取第一行;拒绝权限大于 0600 的文件
内联inline:⚠️ 受限所有平台配置中为明文;默认禁用,启用时会在启动时发出警告
1Passwordop://vault/item/field✅ 通过 CLI所有平台需要已通过身份验证的 op CLI;只读
Vaultvault://path#field✅ 通过 CLI所有平台需要已通过身份验证的 vault CLI;只读
Infisicalinfisical://proj/env/KEY✅ 通过 CLI所有平台需要已通过身份验证的 infisical CLI;只读
Dopplerdoppler://proj/config/KEY✅ 通过 CLI所有平台需要已通过身份验证的 doppler CLI;只读

详细说明、各后端的设置方法以及如何注册插件解析器: docs/backends.md。

威胁模型

威胁缓解措施
模型上下文泄漏结构性防护:值不会越过工具层;仅传递名称和掩码
命令输出回显密钥强制脱敏(精确匹配 + URL/Base64 变体 + 通用模式),失败时默认拒绝
Agent 转储环境变量(env、printenv、/proc/*/environ,……)通过硬性阻止名单拦截(可通过 security.dangerousCommands 配置:添加额外模式,或设置 mode: warn 以允许并审计)+ shell_exec_blocked 审计事件
同一 UID 的本地进程读取 /proc/PID/environ操作系统层面的限制,无法彻底解决;按命令注入可缩短暴露窗口。明确的边界。
密钥长期驻留默认按命令注入;会话采用空闲 TTL 回收 + 可立即 revoke
规则配置错误导致到处注入rule_validate / rule_list 提供静态警告;mergeStrategy 默认为 override;requireConfirm 规则要求交互式批准(没有征询能力时默认拒绝)
配置文件泄漏配置只存储引用,从不存储值;默认禁用 inline:;强制将存储文件权限设为 0600

完整讨论:docs/design-spec.md §7。 请根据 SECURITY.md 私下报告漏洞。

数据布局

~/.vaultshell/
  config.yaml     # main config
  rules.yaml      # injection rules + secret refs (refs only, never values)
  secrets.enc     # encrypted-file backend (0600)
  audit/          # JSONL audit, redacted

VAULTSHELL_HOME 可覆盖数据目录(测试使用)。

开发

npm run build   # tsc
npm test        # vitest — redactor property tests, backend round-trips,
                # rule matching, shell_exec end-to-end

请参阅 CONTRIBUTING.md——其中包括每个 PR 都必须遵守的安全红线。

许可证

MIT © 2026 vaultshell 贡献者

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。