关于 oauth-auditor
oauth-auditor 是面向开发者的 MCP 服务,用于审查 MCP 服务中的 OAuth 授权代码。它检测指定的 OAuth 2.1 反模式,并可为 CI/CD 输出 SARIF 结果。
主要功能
- 01扫描六类 OAuth 反模式
- 02检查源文件和目录
- 03输出 SARIF 2.1.0 结果
- 04支持 guardbee.yml 配置
适用场景
- 01发布前审查 MCP 服务授权代码
- 02在 CI/CD 中加入 OAuth 检查
- 03检查代码片段或文件中的授权风险
MCP 相关
提供扫描文本、文件和目录以及列出支持模式的 MCP 工具。另有用于扫描代码和探测运行中端点的命令行工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
4收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| label | string | 否 | 在发现结果中显示的可选标签(例如文件名) |
| content | string | 是 | 要扫描的代码内容 |
详细介绍
@guardbee/mcp-oauth-auditor
🇬🇧 English | 🇹🇷 Türkçe | 🇨🇳 中文 | 🇯🇵 日本語 | 🇰🇷 한국어 | 🇧🇷 Português | 🇪🇸 Español | 🇩🇪 Deutsch
一个 MCP(Model Context Protocol)服务,用于扫描 MCP 服务自身的授权代码,检查其中是否存在 MCP 规范「安全注意事项」章节列出的 OAuth 2.1 反模式。
MCP 规范并未对此含糊其辞——它明确指出,令牌直通(不交换令牌或重新限定其作用域,而是将客户端的令牌原样转发给下游 API)和缺少受众验证(接受 aud 声明并非为此服务签发的令牌),是作为 OAuth 资源服务器的服务最主要的授权失效模式。此程序包会检查这两种模式,以及同一类别中的另外三种相关反模式。
默认情况下,遥测功能处于关闭状态。设置
GUARDBEE_TELEMETRY=1后,它会发送服务、工具、成功状态、持续时间以及简短的参数值(例如文件路径);较长的字符串以及content、token或password等字段会替换为占位符。请参阅@guardbee/mcp-telemetry。
Claude ──► oauth-auditor ──► Your MCP server's auth code
│
├─ token-passthrough (client's token forwarded unchanged downstream)
├─ token-validation (jwt.verify() with no audience check)
├─ discovery-ssrf (OAuth/OIDC discovery URL built from client input)
├─ pkce (authorization request missing code_challenge)
├─ redirect-validation (redirect_uri checked with startsWith/includes, not exact match)
└─ secrets-exposure (hardcoded client_secret)
为什么特别关注这两种模式
令牌直通之所以重要,是因为客户端提交给此服务的令牌,其作用域和受众都是此服务,而不是服务自身的工具处理程序接下来调用的任何下游 API。原样转发令牌,就意味着下游服务在信任一个自己从未签发过的凭据,而这一决定是由服务端作出的,原始令牌签发方并未批准。
缺少受众验证是从另一个方向出现的同类失效:jwt.verify(token, key) 能确认令牌的签名有效,却无法说明令牌是为谁签发的。如果没有显式的 audience 检查,那么为完全无关的资源服务器签发的令牌——只要它恰好与当前服务共用同一个签发方或签名密钥——在此处也会成功通过验证。这正是 MCP 规范警告的典型「困惑的代理」替代攻击。
另外三种模式也与这一主题紧密相关,都是具体实例:使用客户端提供的输入构造 OAuth/OIDC 发现 URL(这正是某个已披露 CVE 背后的攻击模式);通过前缀或子字符串检查而非精确匹配来验证 redirect_uri(可绕过开放重定向防护);以及在授权请求中悄然遗漏 PKCE(OAuth 2.1 无条件要求 PKCE,而不仅仅是针对公共客户端)。
功能
- 6 个类别:token-passthrough、token-validation、discovery-ssrf、pkce、redirect-validation、secrets-exposure
- 其中两项检查(缺少 audience 验证、缺少 PKCE)会在调用点附近查找缺失项,而不是匹配固定正则表达式——它们会提取完整的
jwt.verify(...)调用(或授权请求 URL 的构造过程),并确认附近确实没有audience:/code_challenge,而不只是恰好匹配到字符串中的某个位置 - 输出 SARIF 2.1.0——支持 CI/CD 集成(GitHub Code Scanning 等)
- 支持通过
guardbee.yml使用配置文件 - 18 项单元测试——每种模式都包含一个正向场景和一个负向(误报)场景,另有一个完全正确的 OAuth 流程,其结果为零项发现。开发过程中发现并修复了一个实际的正则表达式错误(
]字符后跟了一个无法匹配的\b,因为]不是单词字符——导致方括号表示法的请求头访问形式被悄然漏检)。已针对包含全部 6 种故意植入的反模式的测试样例完成端到端验证(全部 6 种均被检出),并针对整个 guardbee-mcp 单体仓库完成验证(401 个文件——任何真实第三方代码中均无发现;唯一非测试匹配项来自扫描器自身的模式定义源码:其中一处在正则表达式字面量中以文本形式包含字符串jwt.verify(,另一处在文档注释中包含该字符串,并非实际的易受攻击用法)
快速开始
Claude Desktop / MCP 客户端
{
"mcpServers": {
"guardbee-oauth-auditor": {
"command": "npx",
"args": ["-y", "@guardbee/mcp-oauth-auditor"]
}
}
}
CLI(CI/CD)
npx @guardbee/mcp-oauth-auditor scan ./src --fail-on=high --format=sarif > results.sarif
MCP 工具
| 工具 | 描述 |
|---|---|
scan_text | 扫描代码片段 |
scan_file | 扫描单个文件 |
scan_directory | 递归扫描目录 |
list_patterns | 按类别列出所有受支持的模式 |
检测到的模式
| 类别 | 模式 | 严重性 | OWASP |
|---|---|---|---|
| token-passthrough | token_passthrough_to_downstream | critical | MCP07 |
| token-validation | missing_audience_validation | high | MCP07 |
| discovery-ssrf | oauth_discovery_ssrf | critical | MCP07 |
| pkce | missing_pkce_on_auth_request | high | MCP07 |
| redirect-validation | loose_redirect_uri_validation | high | MCP07 |
| secrets-exposure | hardcoded_oauth_client_secret | high | MCP07 |
| state-handle | predictable_state_handle(+ Python)——使用 Math.random、Date.now 或计数器生成的 state / session 句柄 | high | MCP07 |
| state-handle | state_handle_not_bound_to_user——从工具参数获取句柄并进行查找,却未检查该句柄是否属于调用者 | medium | MCP07 |
| mix-up | missing_iss_validation——兑换授权码时未检查 iss(RFC 9207) | medium | MCP07 |
| auth-url | auth_url_scheme_not_validated——打开服务端提供的 URL 时未检查 scheme(javascript:、data:、file:) | high | MCP07 |
| auth-url | auth_url_opened_via_shell——通过 shell 将 URL 插入 open / xdg-open / start 命令 | critical | MCP05 |
| local-exposure | local_http_server_unauthenticated——HTTP MCP 传输未进行身份验证 | high | MCP07 |
| local-exposure | missing_host_origin_check——未验证 Host / Origin(DNS 重绑定) | medium | MCP07 |
| local-exposure | listen_all_interfaces——MCP 服务绑定到 0.0.0.0 | medium | MCP07 |
Python 和 Go
语言类型根据文件扩展名确定,Python 和 Go 专属规则仅适用于对应语言的文件。
- Python(FastAPI / Starlette / Flask、PyJWT、python-jose、authlib):
python_missing_audience_validation(jwt.decode未设置audience=,且 authlib 未设置claims_options中的aud)、python_audience_verification_disabled("verify_aud": False)、python_token_passthrough_to_downstream(在requests/httpx/ 客户端调用中传递Authorization标头或全部request.headers)、authlibcreate_authorization_url/authorize_redirect未设置code_challenge时触发的missing_pkce_on_auth_request,以及发现服务 SSRF、重定向、state 和0.0.0.0规则。 - Go(golang-jwt / jwx、go-oidc、golang.org/x/oauth2、go-sdk 和 mcp-go HTTP 传输):
go_missing_audience_validation(jwt.Parse未设置jwt.WithAudience)、go_oidc_client_id_check_skipped、go_token_passthrough_to_downstream(out.Header.Set("Authorization", r.Header.Get("Authorization")))、go_hardcoded_oauth_client_secret、go_loose_redirect_uri_validation(strings.HasPrefix)、go_predictable_state_handle(math/rand、time)、go_oauth_discovery_ssrf、go_auth_url_opened_via_shell、AuthCodeURL未设置S256ChallengeOption时触发的missing_pkce_on_auth_request,以及将ListenAndServe(":8080")识别为listen_all_interfaces。 - 两者通用:
token_passthrough_via_variable— 读取传入的Authorization标头并存入变量,随后将其放入传出请求。
每项发现都会链接到 MCP 规范《安全最佳实践》 中对应的章节(SARIF helpUri),并带有作为 SARIF 标签的 OWASP MCP Top 10 编号。较新的规则是针对单个文件的启发式检查:在其他模块中执行的检查(如身份验证中间件或辅助函数中的 iss 比较)无法被检测到。
实时探测
npx @guardbee/mcp-oauth-auditor probe http://127.0.0.1:3000/mcp
对运行中的 HTTP MCP 端点执行只读检查:它是否会在没有凭据的情况下响应 initialize(probe_unauthenticated_access),以及是否接受外部 Host(probe_dns_rebinding_host_accepted)或 Origin(probe_foreign_origin_accepted)?它不会发送凭据,不会调用 initialize 以外的任何内容,会关闭它打开的任何会话,并会拒绝解析到公共地址的主机,除非指定 --allow-public。仅限 CLI:Agent 无法通过 MCP 工具启动它。
配置(guardbee.yml)
oauth-auditor:
fail-on: high # any | critical | high | medium | none
max-files: 5000
exclude:
- ".test.ts"
局限性(有意如此)
- TypeScript/JavaScript、Python 和 Go。 每种语言都针对其常用库设有规则(见上文)。其他语言(Rust、Java、C# 等)和其他库只有在代码形态恰好与这些规则相符时才会被匹配,例如字面量
client_secret或response_type=code。 - 启发式检查,不是完整的 OAuth 一致性测试。 它会在源代码中查找特定反模式,而不是对运行中的授权服务器执行实时协议一致性检查。它无法发现 OAuth 流程的所有错误实现方式,只检查 MCP 规范指出风险最高的少数几项。
- 基于缺失项的检查(audience、PKCE)使用有界文本窗口,而不是真正的解析器——如果
jwt.verify()调用的选项对象是在远离调用位置的地方构建的(通过变量传入,而不是内联对象),就无法正确检查其中的audience。
开发
npm run build
npm test
许可证
MIT — GuardBee
反馈
有问题、想法或误报?请在 GitHub Discussions 中发起讨论,或提交 issue。如果 GuardBee 对你有帮助,请在项目仓库点一个 ⭐,帮助其他人发现它。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。