权限降级工具

动态降级用户凭证权限为可配置子集以用于AI工具,确保安全合规。

  • by kbroughton
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 kbroughton/downscoping-mcp

使用说明

降低mcp

将用户凭据权限降级为可配置的子集,供AI工具使用。用户应该已经获得了日常工作的权限子集,这些权限映射到特定GCP项目或AWS帐户中的服务。降级是指进一步限制行动以符合公司标准。

权限授予通常是 <Action allowed> on <Resource>.应对措施会影响 <Action allowed> 例如从读/写到只读。

例子

  • 允许读取但不允许写入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)。看 docs/GITHUB_DONSCOPING.md.
  • 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-write

4.登记挂钩

添加到您的项目 .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模式)

  1. 阅读 env_var 从当前流程环境
  2. 如果未设置,请回退到 inject_as 变量(使用环境凭据)
  3. 如果两者都没有设置,则将命令原封不动地传递

建筑

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命令行界面 gh token_slot GITHUB_DONSCOPING.md
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 GITHUB_DONSCOPING.md

可以通过扩展来添加其他服务 config.yaml --无需更改代码。


安全说明

  • 令牌值为 shlex.quote-在shell注入之前转义,以防止通过精心编制的令牌值进行命令注入。
  • 待定 TOKEN=value 在命令使令牌在进程列表中可见之前(ps aux).对于更高安全性的环境,使用通过文件描述符或机密管理器注入令牌的凭据助手。
  • 阻止消息包括匹配的规则名称和模式,因此原因始终是可审计的。
  • 回退到环境 inject_as 令牌意味着,如果您尚未配置作用域令牌,则使用环境凭据传递命令。集 DOWNSCOPE_REQUIRE_SCOPED=1 (未来)强化这一点。
  • .claude/settings.json 应忽略包含本地路径的内容——请参见 .gitignore 在这个回购中。

发展

pip install -e .
pytest tests/

许可证

麻省理工学院