降低mcp
将用户凭据权限降级为可配置的子集,供AI工具使用。用户应该已经获得了日常工作的权限子集,这些权限映射到特定GCP项目或AWS帐户中的服务。降级是指进一步限制行动以符合公司标准。
权限授予通常是 on .应对措施会影响 `` 例如从读/写到只读。
例子
- 允许读取但不允许写入Google Drive文档
- 允许GitHub读取PR,但不合并或批准
- 允许读取日志,但不允许部署到GCP中的项目
______________________________________________________________________
问题
Claude Code使用您环境中存在的任何凭据运行。可以读取文件的模型也可以调用 gh repo delete, gcloud projects delete,或 aws iam delete-user --使用相同的令牌。一次越狱、迅速注射或混乱的副攻击就足以造成伤害。意外错误也是如此——如果分支保护或GitHub操作配置不正确,Claude直接推送到发布分支可能会触发部署管道。
为什么采用这种方法?
显而易见的替代方案是为AI使用创建专用的低权限IAM角色或服务帐户——每个团队、每个环境一个。这很快就会达到硬极限。
典型的 ~/.aws/config 已经有60多个档案,涵盖了不同的账户和角色。与AI特定的缩减对应物相比,这意味着需要120多个配置文件、持续的IaC维护和每个工程师的配置 .claude/settings.local.json 连接正确的轮廓。AWS的默认IAM角色配额为每个帐户1000个(更高的限额需要配额增加请求),每个新角色都是另一回事,需要审计、轮换并与原始角色保持同步。
此工具采用了一种不同的方法:在呼叫时动态缩小范围,而无需接触IAM。其工作原理与 aws sts assume-role --policy-arns,这将假定角色的有效权限限制为角色策略和提供的策略ARN的交集。在这里,交集是在签入项目的YAML文件中定义的,而不是在IAM策略文档中定义的——但语义是相同的。使用您现有的凭据;根据您定义的规则,每个操作的有效能力都会缩小。
一个重要的财产被保留了下来: 此工具只能减少特权,而不能增加特权。 它设置了护栏,以确保AI工具的使用安全并符合公司政策,而不需要对IAM设置进行任何更改。
______________________________________________________________________
运作原理
对每个命令的规则进行自上而下的评估。第一场比赛获胜。有三种可能的结果:
| 行动 | 行为 |
|---|---|
allow | 为匹配的插槽注入作用域令牌;命令继续 |
review | 阻止命令;告诉Claude让用户手动运行它 |
deny | 阻止命令;告诉克劳德,人工智能不允许使用 |
阻止消息包括规则名称和匹配的模式,因此原因总是明确的。
第1级——动态降档(首选)
本机云STS在呼叫时从您的环境凭据中导出受限令牌。不需要新的IAM角色或预先配置的令牌。
- 亚马逊云服务:
sts:GetFederationToken或sts:AssumeRole采用内联策略。有效权限=您的身份策略和内联策略的交集。看 docs/AWS_DOWNSCOPING.md. - 谷歌云平台:通过凭据访问边界
sts.googleapis.com。将环境令牌限制为特定的资源和角色。 仅支持云存储。 对于其他GCP服务,则回到OAuth范围限制。看 docs/GCP_DOWNSCOPING.md.
第2层——令牌插槽(回退)
当不存在动态API时使用。根据YAML规则为每个操作选择预先配置的窄范围令牌。
- GitHub:细粒度PAT(不提供动态缩减API)。看 .
- GCP非GCS服务:OAuth范围限制通过
generateAccessToken仅限API级别的粒度。 - kubectl 的:Kubernetes ServiceAccount令牌绑定到最小RBAC角色。EKS和GKE集群可以使用支持云提供商的动态缩减——请参阅 docs/KUBECTL_DOWNSCOPING.md.
两种执行模式
模式1-Bash钩子(CLI工具)
A. PreToolUse 钩子拦截每个 Bash 工具调用。如果命令以已知的服务二进制文件开头(gh, gcloud, aws, kubectl),钩子将参数与YAML规则进行匹配,计算操作,然后用作用域标记重写命令或发出块消息。克劳德从未见过重写。
模式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: ""
# 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 "}}
│
└─ 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命令行界面 | gh | token_slot | |
| AWS-CLI | aws | sts_policy(首选),token_slot | AWS_DOWNSCOPING.md |
| 谷歌云 | gcloud | 凭证_访问_边界(GCS)、oauth_scope、令牌_slot | GCP_向下范围.md |
| 库贝内特斯 | kubectl | token_slot;EKS/GKE动态(未来) | KUBECTL_DONSCOPING.md |
| MCP服务器 | 代理 | token_slot |
可以通过扩展来添加其他服务 config.yaml --无需更改代码。
______________________________________________________________________
安全说明
- 令牌值为
shlex.quote-在shell注入之前转义,以防止通过精心编制的令牌值进行命令注入。 - 待定
TOKEN=value在命令使令牌在进程列表中可见之前(ps aux).对于更高安全性的环境,使用通过文件描述符或机密管理器注入令牌的凭据助手。 - 阻止消息包括匹配的规则名称和模式,因此原因始终是可审计的。
- 回退到环境
inject_as令牌意味着,如果您尚未配置作用域令牌,则使用环境凭据传递命令。集DOWNSCOPE_REQUIRE_SCOPED=1(未来)强化这一点。 .claude/settings.json应忽略包含本地路径的内容——请参见.gitignore在这个回购中。
______________________________________________________________________
发展
pip install -e .
pytest tests/______________________________________________________________________
许可证
麻省理工学院
