downscoping-mcp
downscoping-mcp
将用户凭证权限降级为可配置的子集,供 AI 工具使用。用户在日常工作中通常已经拥有了一组映射到特定 GCP 项目或 AWS 账户服务的权限。降级(Downscoping)是指进一步限制操作以符合公司标准。
权限授予通常是 <Action allowed> on <Resource>。降级通过减少能力来影响 <Action allowed>,例如从读/写变为只读。
示例
允许读取但禁止写入 Google Drive 文档
允许读取 GitHub PR 但禁止合并或批准
允许读取日志但禁止部署到 GCP 项目
问题
Claude Code 使用环境中存在的任何凭证运行。一个可以读取文件的模型也可以使用相同的令牌调用 gh repo delete、gcloud projects delete 或 aws iam delete-user。一次越狱、提示词注入或混淆代理攻击就足以造成损害。意外错误也是如此——如果分支保护或 GitHub Actions 配置不当,Claude 直接推送到发布分支可能会触发部署流水线。
Related MCP server: MCP Airlock
为什么选择这种方法?
显而易见的替代方案是为 AI 使用创建专用的低权限 IAM 角色或服务账户——每个团队、每个环境一个。这很快就会遇到硬性限制。
典型的 ~/.aws/config 已经有 60 多个配置文件,涵盖了不同的账户和角色。如果为 AI 专门创建降级副本,意味着会有 120 多个配置文件、持续的 IaC 维护工作,并且需要在 .claude/settings.local.json 中为每个工程师进行配置以连接正确的配置文件。AWS 每个账户的默认 IAM 角色配额为 1,000 个(更高的限制需要申请增加配额),并且每个新角色都需要审计、轮换并与原始角色保持同步。
该工具采用了不同的方法:在调用时动态降级,无需触及 IAM。它的工作原理类似于 aws sts assume-role --policy-arns,后者将所承担角色的有效权限限制为角色策略与所提供策略 ARN 的交集。在这里,交集是在签入项目的 YAML 文件中定义的,而不是在 IAM 策略文档中——但语义是相同的。使用您现有的凭证;它们的有效能力会根据您定义的规则按操作进行缩减。
保留了一个重要属性:此工具只能降低权限,绝不能增加权限。 它设置了护栏,以确保 AI 工具的使用安全并符合公司政策,而无需更改您的 IAM 设置。
工作原理
规则会针对每个命令从上到下进行评估。第一个匹配项生效。有三种可能的结果:
操作 | 行为 |
| 为匹配的槽位注入降级令牌;命令继续执行 |
| 阻止命令;告知 Claude 要求用户手动运行 |
| 阻止命令;告知 Claude 该操作不允许 AI 使用 |
阻止消息包含规则名称和匹配的模式,因此原因始终是明确的。
第一层 — 动态降级(首选)
原生云 STS 在调用时从您的环境凭证中派生受限令牌。无需新的 IAM 角色或预配置令牌。
AWS:
sts:GetFederationToken或带有内联策略的sts:AssumeRole。有效权限 = 您的身份策略与内联策略的交集。请参阅 docs/AWS_DOWNSCOPING.md。GCP: 通过
sts.googleapis.com的凭证访问边界(Credential Access Boundary)。将环境令牌限制为特定资源和角色。仅支持 Cloud Storage。 对于其他 GCP 服务,回退到 OAuth 范围限制。请参阅 docs/GCP_DOWNSCOPING.md。
第二层 — 令牌槽(回退)
在没有动态 API 时使用。根据 YAML 规则为每个操作选择预配置的窄范围令牌。
GitHub: 细粒度 PAT(没有可用的动态降级 API)。请参阅 docs/GITHUB_DOWNSCOPING.md。
GCP 非 GCS 服务: 通过
generateAccessToken进行 OAuth 范围限制。仅限 API 级别粒度。kubectl: 绑定到最小 RBAC 角色的 Kubernetes ServiceAccount 令牌。EKS 和 GKE 集群可以使用底层云提供商的动态降级——请参阅 docs/KUBECTL_DOWNSCOPING.md。
两种执行模式
模式 1 — Bash 钩子(CLI 工具)
PreToolUse 钩子会拦截每个 Bash 工具调用。如果命令以已知的服务二进制文件(gh、gcloud、aws、kubectl)开头,钩子会将参数与您的 YAML 规则进行匹配,评估操作,并使用降级令牌重写命令或发出阻止消息。Claude 永远看不到重写过程。
模式 2 — MCP 代理
MCP 代理包装上游 MCP 服务器。在转发每个工具调用之前,它会应用相同的 YAML 规则,为该特定工具注入降级令牌。目前支持 github-pr-issue-analyser 服务器;其他服务器是未来的扩展。
快速入门
1. 安装
pip install -e .2. 配置凭证
在您的 shell 配置文件或 CI 环境中导出降级令牌:
# GitHub (token_slot mode — only option for GitHub)
export GITHUB_TOKEN_READONLY=ghp_... # fine-grained: contents:read, issues:read
export GITHUB_TOKEN_ORG_WRITE=ghp_... # fine-grained: issues:write, pull_requests:write
# GCP (token_slot fallback — preferred is CAB via google.auth.downscoped)
export GCLOUD_TOKEN_VIEWER=ya29....
export GCLOUD_TOKEN_EDITOR=ya29....
# AWS (token_slot fallback — preferred is sts:GetFederationToken)
export AWS_ACCESS_KEY_ID_READONLY=AKIA...3. 创建策略文件
cp config.example.yaml .claude/downscoping.yaml根据您组织的访问模型进行编辑。downscope_mode 字段为每个服务选择机制:
version: 1
services:
aws:
downscope_mode: sts_policy # Tier 1: derive restricted token from ambient creds
inline_policy:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: ["s3:GetObject", "s3:ListBucket", "ec2:Describe*"]
Resource: "*"
rules:
- name: "S3 writes require review"
match:
args_pattern: "s3 (cp|mv|rm|sync) .* s3://"
action: review
- name: "IAM mutations denied"
match:
args_pattern: "iam (create|delete|put|attach|detach)"
action: deny
gh:
downscope_mode: token_slot # Tier 2: GitHub has no dynamic API
token_slots:
readonly:
env_var: GITHUB_TOKEN_READONLY
inject_as: GITHUB_TOKEN
org-write:
env_var: GITHUB_TOKEN_ORG_WRITE
inject_as: GITHUB_TOKEN
default_slot: readonly
rules:
- name: "repo deletion denied"
match:
args_pattern: "repo delete|repo rename"
action: deny
- name: "pr merge requires human review"
match:
args_pattern: "pr merge"
action: review
- name: "permitted writes use org-write token"
match:
args_pattern: "pr (create|edit)|issue (create|edit)|push"
action: allow
slot: org-write4. 注册钩子
添加到项目的 .claude/settings.json 中:
{
"env": {
"CLAUDE_PLUGIN_ROOT": "/path/to/downscoping-mcp"
},
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/pre_tool_use.py",
"timeout": 5
}
]
}
]
}
}5. (可选) 启用 MCP 代理
添加到项目根目录的 .mcp.json 中:
{
"mcpServers": {
"credential-downscope-proxy": {
"command": "python3",
"args": ["-m", "credential_downscope.mcp_proxy"],
"env": {
"PYTHONPATH": "${CLAUDE_PLUGIN_ROOT}/src",
"GITHUB_INTEGRATION_SRC": "/path/to/upstream-mcp-server/src"
}
}
}
}策略文件参考
规则操作
rules:
- name: "human-readable name — appears in block messages"
match:
args_pattern: "<regex matched against CLI args after the binary>"
# OR for MCP tools:
tools: [tool_name_1, tool_name_2]
action: allow # inject scoped token (default if action omitted)
slot: readonly # which token slot to use (action: allow only)
- name: "example deny"
match:
args_pattern: "iam delete"
action: deny # blocked; Claude told it is not permitted for AI use
- name: "example review"
match:
args_pattern: "s3 cp .* s3://"
action: review # blocked; Claude told to ask user to run manually规则顺序很重要 — 规则从上到下进行评估;第一个匹配项生效。将特定的 deny/review 规则放在宽泛的 allow 规则之前。
令牌解析顺序 (token_slot 模式)
从当前进程环境中读取
env_var如果未设置,回退到
inject_as变量(使用环境凭证)如果两者都未设置,则按原样传递命令
架构
Claude Code
│
├─ Bash tool call ──► PreToolUse hook (hooks/pre_tool_use.py)
│ │
│ ├─ load .claude/downscoping.yaml
│ ├─ detect service binary
│ ├─ match args against rules → RuleDecision
│ │
│ ├─ action=deny → {"continue": false, "stopReason": "...denied..."}
│ ├─ action=review → {"continue": false, "stopReason": "...run manually..."}
│ └─ action=allow → {"updatedInput": {"command": "TOKEN=value <cmd>"}}
│
└─ MCP tool call ──► credential-downscope-proxy (mcp_proxy.py)
│
├─ match tool name against MCP rules → RuleDecision
├─ inject scoped token into env
└─ forward to upstream MCP server支持的服务
服务 | 二进制 / 接口 | 降级模式 | 文档 |
GitHub CLI |
| token_slot | |
AWS CLI |
| sts_policy (首选), token_slot | |
Google Cloud |
| credential_access_boundary (GCS), oauth_scope, token_slot | |
Kubernetes |
| token_slot; EKS/GKE 动态 (未来) | |
MCP 服务器 | 代理 | token_slot |
可以通过扩展 config.yaml 添加其他服务——无需更改代码。
安全说明
令牌值在 shell 注入前会经过
shlex.quote转义,以防止通过精心构造的令牌值进行命令注入。在命令前添加
TOKEN=value会使令牌在进程列表 (ps aux) 中可见。对于更高安全性的环境,请使用通过文件描述符或密钥管理器注入令牌的凭证助手。阻止消息包含匹配的规则名称和模式,因此原因始终是可审计的。
回退到环境
inject_as令牌意味着如果您尚未配置降级令牌,命令将使用环境凭证通过。设置DOWNSCOPE_REQUIRE_SCOPED=1(未来功能)以加强此限制。包含本地路径的
.claude/settings.json应该被 gitignore 忽略——请参阅此仓库中的.gitignore。
开发
pip install -e .
pytest tests/许可证
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
Security & DLP proxy for MCP: tool-poisoning scans, PII redaction on tool args/results. Beta.
Fail-closed policy guardrails for AI agents running kubectl, terraform, helm, and argocd.
- gatewayOAuthai.sealgate
MCP gateway with runtime security policy, tool-call-level control, and audit of agent actions.
Security firewall for AI agents — scans MCP calls for injection, secrets, and risks.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenancePolicy-enforcing MCP proxy that blocks dangerous tool calls before they execute. Protects credentials, filesystem, shell, and databases across Claude Desktop, Cursor, Windsurf, and OpenClaw.6 npm39Apache 2.0
- AlicenseCqualityDmaintenanceEnables secure, zero-trust access to MCP tools through short-lived, signed capability leases that bind tool execution to specific sessions, intents, and constraints. Prevents prompt injection attacks and privilege escalation with dynamic risk scoring, policy enforcement, and tamper-evident audit logging.41MIT
- AlicenseNot gradedqualityAmaintenanceSecurity gateway for MCP tool calls. Sits between your LLM client and MCP servers, enforcing per-tool policies (allow/block/approve/read-only), logging every call, and pausing dangerous operations for human approval in terminal or Slack.01MIT
- AlicenseNot gradedqualityCmaintenanceRuntime proxy that intercepts and blocks MCP tool calls based on YAML-defined policies, enforcing security rules for AI agents like Claude Code or Cursor.44 npm1Apache 2.0