Skip to main content
Glama
kbroughton
by kbroughton

downscoping-mcp

Herabstufung von Benutzerberechtigungen auf eine konfigurierbare Teilmenge zur Verwendung durch KI-Tools. Ein Benutzer sollte bereits über eine Teilmenge von Berechtigungen für die tägliche Arbeit verfügen, die Diensten in bestimmten GCP-Projekten oder AWS-Konten zugeordnet ist. Downscoping bezieht sich auf die weitere Einschränkung der Aktionen, um Unternehmensstandards zu entsprechen.

Berechtigungszuweisungen sind typischerweise <Aktion erlaubt> auf <Ressource>. Das Downscoping wirkt sich auf die <Aktion erlaubt> aus, indem es die Fähigkeiten reduziert, zum Beispiel von Lesen/Schreiben auf Nur-Lese-Zugriff.

Beispiele

  • Lesezugriff, aber kein Schreibzugriff auf Google Drive-Dokumente erlauben

  • GitHub-Lesezugriff für PRs erlauben, aber kein Zusammenführen oder Genehmigen

  • Lesen von Protokollen erlauben, aber kein Deployment in ein Projekt in GCP


Problem

Claude Code läuft mit den Anmeldeinformationen, die in Ihrer Umgebung vorhanden sind. Ein Modell, das Dateien lesen kann, kann auch gh repo delete, gcloud projects delete oder aws iam delete-user aufrufen — unter Verwendung desselben Tokens. Ein einziger Jailbreak, Prompt-Injection oder ein Confused-Deputy-Angriff reicht aus, um Schaden anzurichten. Das Gleiche gilt für versehentliche Fehler — wenn Claude direkt auf einen Release-Branch pusht, kann dies eine Deployment-Pipeline auslösen, falls Branch-Schutzmaßnahmen oder GitHub Actions nicht korrekt konfiguriert sind.

Related MCP server: MCP Airlock

Warum dieser Ansatz?

Die offensichtliche Alternative ist das Erstellen dedizierter IAM-Rollen oder Dienstkonten mit geringen Rechten für die KI-Nutzung — eine pro Team, pro Umgebung. Dies stößt schnell an harte Grenzen.

Eine typische ~/.aws/config hat bereits über 60 Profile, die verschiedene Konten und Rollen abdecken. Dies mit KI-spezifischen, downscoped Gegenstücken zu verdoppeln, bedeutet über 120 Profile, laufende IaC-Wartung und eine Konfiguration pro Ingenieur in .claude/settings.local.json, um das richtige Profil zu verknüpfen. AWS hat ein Standard-IAM-Rollenkontingent von 1.000 pro Konto (höhere Limits erfordern eine Kontingenterhöhungsanfrage), und jede neue Rolle ist eine weitere Sache, die geprüft, rotiert und mit dem Original synchron gehalten werden muss.

Dieses Tool verfolgt einen anderen Ansatz: Downscoping dynamisch zum Zeitpunkt des Aufrufs, ohne IAM zu berühren. Es funktioniert analog zu aws sts assume-role --policy-arns, was die effektiven Berechtigungen einer angenommenen Rolle auf die Schnittmenge der Richtlinien der Rolle und der bereitgestellten Richtlinien-ARNs beschränkt. Hier wird die Schnittmenge in einer YAML-Datei definiert, die in Ihr Projekt eingecheckt ist, anstatt in einem IAM-Richtliniendokument — aber die Semantik ist dieselbe. Ihre vorhandenen Anmeldeinformationen werden verwendet; ihre effektiven Fähigkeiten werden pro Operation gemäß den von Ihnen definierten Regeln eingeschränkt.

Eine wichtige Eigenschaft bleibt erhalten: Dieses Tool kann Berechtigungen nur reduzieren, niemals erhöhen. Es setzt Leitplanken, um die Nutzung von KI-Tools sicher und konform mit der Unternehmensrichtlinie zu halten, ohne dass Änderungen an Ihrem IAM-Setup erforderlich sind.


Funktionsweise

Regeln werden für jeden Befehl von oben nach unten ausgewertet. Der erste Treffer gewinnt. Drei Ergebnisse sind möglich:

Aktion

Verhalten

allow

Injiziert das scoped Token für den passenden Slot; Befehl wird ausgeführt

review

Blockiert den Befehl; weist Claude an, den Benutzer zu bitten, ihn manuell auszuführen

deny

Blockiert den Befehl; teilt Claude mit, dass er für die KI-Nutzung nicht zulässig ist

Block-Nachrichten enthalten den Regelnamen und das übereinstimmende Muster, sodass der Grund immer explizit ist.

Stufe 1 — Dynamisches Downscoping (bevorzugt)

Native Cloud-STS leitet zum Zeitpunkt des Aufrufs ein eingeschränktes Token von Ihrer Umgebungs-Anmeldeinformation ab. Keine neuen IAM-Rollen oder vorab bereitgestellte Token erforderlich.

  • AWS: sts:GetFederationToken oder sts:AssumeRole mit einer Inline-Richtlinie. Effektive Berechtigungen = Schnittmenge Ihrer Identitätsrichtlinien und der Inline-Richtlinie. Siehe docs/AWS_DOWNSCOPING.md.

  • GCP: Credential Access Boundary via sts.googleapis.com. Beschränkt das Umgebungs-Token auf bestimmte Ressourcen und Rollen. Nur für Cloud Storage unterstützt. Für andere GCP-Dienste erfolgt ein Fallback auf die OAuth-Bereichsbeschränkung. Siehe docs/GCP_DOWNSCOPING.md.

Stufe 2 — Token-Slots (Fallback)

Wird verwendet, wenn keine dynamische API existiert. Vorab bereitgestellte, eng begrenzte Token werden pro Operation basierend auf YAML-Regeln ausgewählt.

  • GitHub: Fein abgestimmte PATs (keine dynamische Downscoping-API verfügbar). Siehe docs/GITHUB_DOWNSCOPING.md.

  • GCP Nicht-GCS-Dienste: OAuth-Bereichsbeschränkung via generateAccessToken. Nur Granularität auf API-Ebene.

  • kubectl: Kubernetes ServiceAccount-Token, die an minimale RBAC-Rollen gebunden sind. EKS- und GKE-Cluster können das dynamische Downscoping des zugrunde liegenden Cloud-Anbieters nutzen — siehe docs/KUBECTL_DOWNSCOPING.md.

Zwei Durchsetzungsmodi

Modus 1 — Bash-Hook (CLI-Tools)

Ein PreToolUse-Hook fängt jeden Bash-Tool-Aufruf ab. Wenn der Befehl mit einer bekannten Dienst-Binary (gh, gcloud, aws, kubectl) beginnt, gleicht der Hook die Argumente mit Ihren YAML-Regeln ab, bewertet die Aktion und schreibt entweder den Befehl mit einem scoped Token um oder gibt eine Block-Nachricht aus. Claude sieht die Umschreibung nie.

Modus 2 — MCP-Proxy

Ein MCP-Proxy umschließt einen Upstream-MCP-Server. Bevor jeder Tool-Aufruf weitergeleitet wird, wendet er dieselben YAML-Regeln an, um das scoped Token für dieses spezifische Tool zu injizieren. Unterstützt derzeit den github-pr-issue-analyser-Server; andere Server sind eine zukünftige Erweiterung.


Schnellstart

1. Installieren

pip install -e .

2. Anmeldeinformationen konfigurieren

Exportieren Sie scoped Token in Ihrem Shell-Profil oder Ihrer CI-Umgebung:

# 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. Eine Richtliniendatei erstellen

cp config.example.yaml .claude/downscoping.yaml

Bearbeiten Sie diese, um sie an das Zugriffsmodell Ihrer Organisation anzupassen. Das Feld downscope_mode wählt den Mechanismus pro Dienst aus:

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. Den Hook registrieren

Fügen Sie dies zu .claude/settings.json Ihres Projekts hinzu:

{
  "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. (Optional) Den MCP-Proxy aktivieren

Fügen Sie dies zu .mcp.json in Ihrem Projektstammverzeichnis hinzu:

{
  "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"
      }
    }
  }
}

Referenz der Richtliniendatei

Regelaktionen

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

Die Reihenfolge der Regeln ist wichtig — Regeln werden von oben nach unten ausgewertet; der erste Treffer gewinnt. Platzieren Sie spezifische deny/review-Regeln vor allgemeinen allow-Regeln.

Token-Auflösungsreihenfolge (Modus token_slot)

  1. Lesen Sie env_var aus der Umgebung des aktuellen Prozesses

  2. Wenn nicht gesetzt, Fallback auf die inject_as-Variable (verwendet die Umgebungs-Anmeldeinformation)

  3. Wenn keines von beiden gesetzt ist, wird der Befehl unverändert durchgereicht


Architektur

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

Unterstützte Dienste

Dienst

Binary / Schnittstelle

Downscope-Modus

Dok

GitHub CLI

gh

token_slot

GITHUB_DOWNSCOPING.md

AWS CLI

aws

sts_policy (bevorzugt), 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 dynamisch (Zukunft)

KUBECTL_DOWNSCOPING.md

MCP-Server

Proxy

token_slot

GITHUB_DOWNSCOPING.md

Zusätzliche Dienste können durch Erweitern von config.yaml hinzugefügt werden — keine Codeänderungen erforderlich.


Sicherheitshinweise

  • Token-Werte werden vor der Shell-Injektion mit shlex.quote maskiert, um Befehlsinjektionen durch manipulierte Token-Werte zu verhindern.

  • Das Voranstellen von TOKEN=value vor einen Befehl macht das Token in Prozesslisten (ps aux) sichtbar. Verwenden Sie für Umgebungen mit höherer Sicherheit einen Credential-Helper, der Token über einen Dateideskriptor oder Secrets Manager injiziert.

  • Block-Nachrichten enthalten den übereinstimmenden Regelnamen und das Muster, sodass der Grund immer prüfbar ist.

  • Der Fallback auf das Umgebungs-Token inject_as bedeutet, dass Befehle bei nicht bereitgestelltem scoped Token mit der Umgebungs-Anmeldeinformation durchgereicht werden. Setzen Sie DOWNSCOPE_REQUIRE_SCOPED=1 (Zukunft), um dies zu härten.

  • .claude/settings.json mit lokalen Pfaden sollte gitignored werden — siehe .gitignore in diesem Repository.


Entwicklung

pip install -e .
pytest tests/

Lizenz

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