关于 Stdio Shellguard
Stdio Shellguard 是面向使用 stdio 的 MCP 服务开发者的 TypeScript 安全工具包,结合受保护的进程执行、源码审计和参考 MCP 服务,并将防护能力作为工具提供。
主要功能
- 01基于允许列表保护 exec 和 spawn
- 02沙箱配置与重放检测
- 03基于 AST 的 Shell 调用审计 CLI
- 04扫描 12 类不安全模式
- 05包含八种工具的参考服务
适用场景
- 01保护 MCP 服务中的 Shell 执行
- 02审计 TypeScript 或 JavaScript 中的不安全调用
- 03为 CI 生成 SARIF 审计结果
MCP 相关
参考 MCP 服务提供八种工具,用于受保护执行、源码审计、重放检查、沙箱状态和信任等级查询。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
8收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| cwd | string | 否 | |
| env | object | 否 | |
| args | array | 是 | |
| command | string | 是 | |
| toolName | string | 是 | |
| timeoutMs | number | 否 | |
| blockOnReplay | boolean | 否 |
详细介绍
属于 StudioMeyer MCP Stack — 在马略卡岛打造 🌴 · 如果你在使用,请点 ⭐
mcp-stdio-shellguard
面向 MCP stdio 服务的纵深防御套件。它通过允许列表 + 沙箱 + 重放检测来封装
child_process.exec/spawn,并提供 AST 审计命令行工具(mcp-shellguard-audit),用于扫描 MCP 服务源码中的未净化 Shell 调用。可防御 Ox-Security MCP stdio-RCE 类漏洞(200k 个易受攻击的服务,于 2026 年 5 月披露)。
- MCP 规范:2025-06-18
- SDK:
@modelcontextprotocol/sdk^1.29.0 - Node:>= 20
- 许可证:MIT
- 作者:Matthias Meyer(StudioMeyer)
安装
npm install mcp-stdio-shellguard
也可以直接运行审计命令行工具,无需安装:
npx -y -p mcp-stdio-shellguard mcp-shellguard-audit scan ./src
功能
包含三个可按需启用的层:
- 库 API — 可直接替换为
guardExec/guardSpawn,在你自己的 MCP 服务中调用。采用默认拒绝的允许列表、沙箱配置文件和重放检测窗口。 - 审计命令行工具 —
mcp-shellguard-audit scan <path>遍历 AST,报告 12 种反模式,严重程度从 LOW(no timeout)到 CRITICAL(exec(\...${userInput}...`)`)。 - MCP 参考服务 —
mcp-stdio-shellguard-demo提供 8 个工具,让 MCP Inspector / Claude Desktop 可以直接使用该套件。
工具(参考服务)
| 工具 | 类型 | 用途 |
|---|---|---|
guard_exec | 具有破坏性 | 防护 child_process.exec。强制使用 args[] 向量、允许列表 + 沙箱 + 重放检测。返回 stdout、stderr、exitCode、canonicalHash、isReplay、trustTier。 |
guard_spawn | 具有破坏性 | 防护 child_process.spawn。返回 stdout/stderr 的 SHA-256 哈希值,而不是完整内容。直接拒绝 shell:true。 |
register_allowlist | 可变更 | 使用可执行文件和参数正则表达式注册工具名称。未注册时默认拒绝。 |
audit_source | 只读 | 扫描 TS/JS 路径中的 Shell 注入反模式。返回 AuditFinding[] + 摘要。 |
audit_report | 只读 | 将审计结果格式化为 markdown / json / SARIF 2.1.0。 |
replay_check | 只读 | 计算调用的规范 SHA-256 哈希值,并报告其是否已在重放检测窗口中。 |
sandbox_status | 只读 | 报告当前启用的沙箱配置文件、具体限制以及 cgroup-v2 是否启用。 |
trust_tier | 只读 | 为已注册工具判定 LOW/MEDIUM/HIGH/CRITICAL 等级,并提供改进建议。 |
沙箱配置文件
| 配置文件 | 超时 | 最大 stdout | 最大 stderr | FD 预算 | cgroup-v2 |
|---|---|---|---|---|---|
strict | 5 s | 1 MB | 256 KB | 32 | yes (cpu/memory) |
standard(默认) | 30 s | 10 MB | 1 MB | 256 | yes |
permissive | 5 min | 100 MB | 10 MB | 1024 | no |
调用方可以通过每次调用的 timeoutMs / fdBudget 收紧限制,但不能超出配置文件设定的范围。
信任等级
| 等级 | 条件 |
|---|---|
| LOW | 工具未注册(默认拒绝) |
| MEDIUM | 已注册,但 argsPatterns 为空(允许任意参数) |
| HIGH | 已设置 argsPatterns,但沙箱或重放跟踪器未启用 |
| CRITICAL | argsPatterns、沙箱和重放均已启用 |
注册工具、设置 argsPatterns,并通过 guardExec/guardSpawn 运行
即可将 LOW 提升至 CRITICAL(它们始终会启用沙箱和重放)。
库快速入门
import {
AllowlistRegistry,
ReplayWindow,
guardExec,
} from "mcp-stdio-shellguard";
const registry = new AllowlistRegistry();
const replay = new ReplayWindow();
registry.register({
toolName: "git-log",
executable: "/usr/bin/git",
argsPatterns: ["^log$", "^--oneline$", "^-n$", "^\\d+$"],
sandboxProfile: "strict",
});
const result = await guardExec(
{
toolName: "git-log",
command: "/usr/bin/git",
args: ["log", "--oneline", "-n", "10"],
},
{ registry, replay },
);
console.log(result.stdout); // → commit lines
console.log(result.trustTier); // → "CRITICAL"
console.log(result.canonicalHash); // → 64-char SHA-256
审计 CLI
mcp-shellguard-audit scan ./src
mcp-shellguard-audit scan ./src --format sarif --output audit.sarif
mcp-shellguard-audit scan ./src --severity-floor HIGH # CI gate
退出码:
0无问题(没有达到或超过阈值的问题)1存在问题2解析 / IO 错误
传递给 scanPath 或 audit_source MCP 工具的自定义 ignoreGlobs 最多可包含 128 个字符串。每个字符串最多为 1024 个 UTF-16 代码单元,并且未转义的分组开符号((、{、[)不得超过 16 个。超过这些限制的输入会在匹配前触发受控错误。
反模式库(12 条规则)
| ID | 严重性 | 触发条件 |
|---|---|---|
exec_template_literal_with_input | CRITICAL | child_process.exec(\ls ${x}`)` |
exec_dynamic_string | CRITICAL | child_process.exec(cmd) |
exec_sync_dynamic_string | CRITICAL | child_process.execSync(cmd) |
eval_near_child_process | CRITICAL | eval(...) |
function_constructor_near_child_process | CRITICAL | new Function(...) |
spawn_dynamic_file_args | HIGH | spawn(bin, userArgs) |
exec_file_dynamic | HIGH | execFile(bin, ...) |
shell_true_option | HIGH | { shell: true } |
os_system_equivalent | HIGH | Deno.run / Bun.spawn |
spawn_literal_dynamic_args | MEDIUM | spawn('git', userArgs) |
unbounded_buffer | LOW | exec 未设置 maxBuffer |
missing_timeout | LOW | exec/spawn 未设置 timeout |
扫描器会在匹配前解析重命名后的 child_process 绑定,因此即使调用通过别名而非字面量 child_process.exec 执行,也能捕获以下危险形式:
const execAsync = promisify(exec); execAsync(\...${x}`)`import cp from "node:child_process"; cp.exec(\...${x}`)`const { exec: sh } = require("child_process"); sh(\...${x}`)`import { exec as run } from "node:child_process"; run(...)
同步变体(spawnSync、execFileSync)沿用对应的异步规则;shell_true_option 也会在 shell 值为字符串({ shell: "/bin/sh" })或动态值时触发,不仅限于字面量 { shell: true }。对非 child_process 函数使用 promisify、从其他模块解构函数,以及 { shell: false } 均不会触发(不会产生误报)。
Pragma 指令
// shellguard:ignore-next-line— 抑制一条问题// shellguard:ignore-file— 抑制整个文件(较少使用;优先按行抑制)
存在原因
Ox-Security 于 2026-05 披露,超过 20 万个 MCP stdio 服务会用模板字面量封装 child_process.exec,并将来自大模型工具参数的用户输入直接传入。LiteLLM v1.83.6 是典型案例(该漏洞已在 1.83.7 中修复)。此软件包是对应的防御性安全方案:可直接集成的防护器 + 扫描器,能够消除此类问题。其设计受到 AWS Linux seccomp 和 Chromium 沙箱分级的启发。
另请参阅
HOOK_RECIPES.md— 可自动拦截危险工具调用的 Claude Code hook 配方CHANGELOG.md— 版本发布历史- Ox-Security MCP 审计:https://venturebeat.com/security/200000-mcp-stdio-servers/
- LiteLLM CVE-2026-XXXX:https://github.com/BerriAI/litellm/security/advisories
许可证
MIT — 版权所有 (c) 2026 Matthias Meyer (StudioMeyer)
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。