Skip to main content
Glama
kbroughton
by kbroughton

downscoping-mcp

AI 도구에서 사용할 수 있도록 사용자 자격 증명 권한을 구성 가능한 하위 집합으로 낮춥니다. 사용자는 일상 업무를 위해 특정 GCP 프로젝트나 AWS 계정의 서비스에 매핑되는 권한 하위 집합을 이미 부여받아야 합니다. 다운스코핑(Downscoping)은 회사 표준을 준수하기 위해 작업을 추가로 제한하는 것을 의미합니다.

권한 부여는 일반적으로 <리소스>에 대한 <허용된 작업> 형태입니다. 다운스코핑은 예를 들어 읽기/쓰기에서 읽기 전용으로 기능을 줄임으로써 <허용된 작업>에 영향을 미칩니다.

예시

  • Google Drive 문서에 대한 읽기는 허용하되 쓰기는 허용하지 않음

  • GitHub PR에 대한 읽기는 허용하되 병합이나 승인은 허용하지 않음

  • GCP 프로젝트의 로그 읽기는 허용하되 배포는 허용하지 않음


문제

Claude Code는 환경에 존재하는 자격 증명을 사용하여 실행됩니다. 파일을 읽을 수 있는 모델은 동일한 토큰을 사용하여 gh repo delete, gcloud projects delete 또는 aws iam delete-user를 호출할 수도 있습니다. 단 한 번의 탈옥(jailbreak), 프롬프트 주입 또는 혼란스러운 대리인(confused-deputy) 공격만으로도 피해를 입히기에 충분합니다. 실수로 인한 오류도 마찬가지입니다. Claude가 릴리스 브랜치에 직접 푸시하면 브랜치 보호나 GitHub Actions가 올바르게 구성되지 않은 경우 배포 파이프라인이 트리거될 수 있습니다.

Related MCP server: MCP Airlock

왜 이 접근 방식인가?

가장 분명한 대안은 AI 사용을 위해 팀별, 환경별로 전용 저권한 IAM 역할이나 서비스 계정을 만드는 것입니다. 이는 곧 한계에 부딪힙니다.

일반적인 ~/.aws/config에는 이미 다양한 계정과 역할을 다루는 60개 이상의 프로필이 있습니다. 이를 AI 전용 다운스코핑 대응 항목으로 두 배로 늘리면 120개 이상의 프로필이 생기고, 지속적인 IaC 유지 관리와 올바른 프로필을 연결하기 위한 .claude/settings.local.json 내의 엔지니어별 구성이 필요합니다. AWS는 계정당 1,000개의 기본 IAM 역할 할당량을 가지고 있으며(더 높은 제한은 할당량 증액 요청이 필요함), 각 새 역할은 감사, 교체 및 원본과 동기화 상태를 유지해야 하는 또 다른 항목입니다.

이 도구는 IAM을 건드리지 않고 호출 시점에 동적으로 다운스코핑하는 다른 접근 방식을 취합니다. 이는 역할의 정책과 제공된 정책 ARN의 교집합으로 가정된 역할의 유효 권한을 제한하는 aws sts assume-role --policy-arns와 유사하게 작동합니다. 여기에서 교집합은 IAM 정책 문서가 아닌 프로젝트에 체크인된 YAML 파일에 정의되지만 의미론은 동일합니다. 기존 자격 증명이 사용되며, 정의한 규칙에 따라 작업별로 유효 기능이 좁혀집니다.

한 가지 중요한 속성이 보존됩니다. 이 도구는 권한을 줄일 수만 있으며 절대 늘릴 수 없습니다. IAM 설정을 변경할 필요 없이 AI 도구 사용을 안전하고 회사 정책을 준수하도록 유지하기 위한 가드레일을 설정합니다.


작동 방식

규칙은 각 명령에 대해 위에서 아래로 평가됩니다. 첫 번째 일치 항목이 적용됩니다. 세 가지 결과가 가능합니다.

작업

동작

allow

일치하는 슬롯에 대해 스코프가 지정된 토큰을 주입; 명령 진행

review

명령 차단; Claude에게 사용자에게 수동으로 실행하도록 요청하라고 지시

deny

명령 차단; Claude에게 AI 사용이 허용되지 않는다고 알림

차단 메시지에는 규칙 이름과 일치하는 패턴이 포함되어 이유를 항상 명확하게 알 수 있습니다.

계층 1 — 동적 다운스코핑 (권장)

네이티브 클라우드 STS는 호출 시점에 주변 자격 증명에서 제한된 토큰을 파생합니다. 새로운 IAM 역할이나 사전 프로비저닝된 토큰이 필요하지 않습니다.

  • AWS: 인라인 정책이 포함된 sts:GetFederationToken 또는 sts:AssumeRole. 유효 권한 = ID 정책과 인라인 정책의 교집합. docs/AWS_DOWNSCOPING.md 참조.

  • GCP: sts.googleapis.com을 통한 자격 증명 액세스 경계(Credential Access Boundary). 주변 토큰을 특정 리소스와 역할로 제한합니다. Cloud Storage에 대해서만 지원됩니다. 다른 GCP 서비스의 경우 OAuth 범위 제한으로 대체됩니다. docs/GCP_DOWNSCOPING.md 참조.

계층 2 — 토큰 슬롯 (대체)

동적 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. 자격 증명 구성

셸 프로필이나 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 CLI

gh

token_slot

GITHUB_DOWNSCOPING.md

AWS CLI

aws

sts_policy (권장), token_slot

AWS_DOWNSCOPING.md

Google Cloud

gcloud

credential_access_boundary (GCS), oauth_scope, token_slot

GCP_DOWNSCOPING.md

Kubernetes

kubectl

token_slot; EKS/GKE 동적 (향후)

KUBECTL_DOWNSCOPING.md

MCP 서버

프록시

token_slot

GITHUB_DOWNSCOPING.md

config.yaml을 확장하여 추가 서비스를 추가할 수 있으며 코드 변경은 필요하지 않습니다.


보안 참고 사항

  • 토큰 값은 조작된 토큰 값을 통한 명령 주입을 방지하기 위해 셸 주입 전에 shlex.quote로 이스케이프 처리됩니다.

  • 명령 앞에 TOKEN=value를 추가하면 프로세스 목록(ps aux)에서 토큰이 표시됩니다. 보안 수준이 높은 환경의 경우 파일 설명자나 비밀 관리자를 통해 토큰을 주입하는 자격 증명 도우미를 사용하십시오.

  • 차단 메시지에는 일치하는 규칙 이름과 패턴이 포함되어 이유를 항상 감사할 수 있습니다.

  • 주변 inject_as 토큰으로의 대체는 스코프가 지정된 토큰을 아직 프로비저닝하지 않은 경우 명령이 주변 자격 증명을 사용하여 통과됨을 의미합니다. 이를 강화하려면 DOWNSCOPE_REQUIRE_SCOPED=1(향후)을 설정하십시오.

  • 로컬 경로가 포함된 .claude/settings.json은 gitignore 처리되어야 합니다. 이 저장소의 .gitignore를 참조하십시오.


개발

pip install -e .
pytest tests/

라이선스

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Policy-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 npm
    39
    Apache 2.0
  • A
    license
    C
    quality
    D
    maintenance
    Enables 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.
    4
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Security 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.
    0
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Runtime 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 npm
    1
    Apache 2.0