downscoping-mcp
downscoping-mcp
Reduce los privilegios de las credenciales de usuario a un subconjunto configurable para su uso por herramientas de IA. Un usuario ya debería tener un subconjunto de permisos para el trabajo diario que se asigna a servicios en proyectos GCP o cuentas AWS específicos. La reducción de privilegios (downscoping) se refiere a restringir aún más las acciones para cumplir con los estándares de la empresa.
Las concesiones de permisos suelen ser <Acción permitida> en <Recurso>. La reducción de privilegios afecta a la <Acción permitida> al reducir las capacidades, por ejemplo, de lectura/escritura a solo lectura.
Ejemplos
Permitir lectura pero no escritura en documentos de Google Drive
Permitir lectura de GitHub para PRs pero no fusionar o aprobar
Permitir la lectura de registros pero no el despliegue en un proyecto en GCP
Problema
Claude Code se ejecuta con las credenciales presentes en tu entorno. Un modelo que puede leer archivos también puede ejecutar gh repo delete, gcloud projects delete o aws iam delete-user, utilizando el mismo token. Un solo jailbreak, inyección de prompts o ataque de "diputado confundido" es suficiente para causar daños. Lo mismo ocurre con los errores accidentales: que Claude haga un push directamente a una rama de lanzamiento puede activar una canalización de despliegue si las protecciones de rama o las GitHub Actions no están configuradas correctamente.
Related MCP server: MCP Airlock
¿Por qué este enfoque?
La alternativa obvia es crear roles IAM o cuentas de servicio dedicadas de bajos privilegios para el uso de la IA: uno por equipo, por entorno. Esto se topa rápidamente con límites estrictos.
Un ~/.aws/config típico ya tiene más de 60 perfiles que cubren diferentes cuentas y roles. Duplicar eso con contrapartes de IA con privilegios reducidos significa más de 120 perfiles, mantenimiento continuo de IaC y configuración por ingeniero en .claude/settings.local.json para conectar el perfil correcto. AWS tiene una cuota predeterminada de 1000 roles IAM por cuenta (los límites más altos requieren una solicitud de aumento de cuota), y cada nuevo rol es una cosa más que auditar, rotar y mantener sincronizada con el original.
Esta herramienta adopta un enfoque diferente: reduce los privilegios dinámicamente en el momento de la llamada, sin tocar IAM. Funciona de forma análoga a aws sts assume-role --policy-arns, que restringe los permisos efectivos de un rol asumido a la intersección de las políticas del rol y los ARN de política suministrados. Aquí, la intersección se define en un archivo YAML incluido en tu proyecto en lugar de en un documento de política IAM, pero la semántica es la misma. Se utilizan tus credenciales existentes; sus capacidades efectivas se reducen por operación de acuerdo con las reglas que definas.
Se conserva una propiedad importante: esta herramienta solo puede reducir privilegios, nunca aumentarlos. Establece barreras de seguridad para mantener el uso de herramientas de IA seguro y conforme a la política de la empresa, sin requerir cambios en tu configuración de IAM.
Cómo funciona
Las reglas se evalúan de arriba a abajo para cada comando. La primera coincidencia gana. Son posibles tres resultados:
Acción | Comportamiento |
| Inyecta el token con privilegios reducidos para la ranura coincidente; el comando continúa |
| Bloquea el comando; le dice a Claude que pida al usuario que lo ejecute manualmente |
| Bloquea el comando; le dice a Claude que no está permitido para uso de IA |
Los mensajes de bloqueo incluyen el nombre de la regla y el patrón coincidente para que el motivo sea siempre explícito.
Nivel 1 — Reducción de privilegios dinámica (preferido)
El STS nativo de la nube deriva un token restringido de tu credencial ambiental en el momento de la llamada. No se requieren nuevos roles IAM ni tokens pre-aprovisionados.
AWS:
sts:GetFederationTokenosts:AssumeRolecon una política en línea. Permisos efectivos = intersección de tus políticas de identidad y la política en línea. Ver docs/AWS_DOWNSCOPING.md.GCP: Límite de acceso a credenciales a través de
sts.googleapis.com. Restringe el token ambiental a recursos y roles específicos. Soportado solo para Cloud Storage. Para otros servicios de GCP, vuelve a la restricción de alcance OAuth. Ver docs/GCP_DOWNSCOPING.md.
Nivel 2 — Ranuras de token (alternativa)
Se utiliza cuando no existe una API dinámica. Se seleccionan tokens pre-aprovisionados con privilegios limitados por operación basados en reglas YAML.
GitHub: PATs de grano fino (no hay API de reducción de privilegios dinámica disponible). Ver docs/GITHUB_DOWNSCOPING.md.
Servicios GCP que no son GCS: Restricción de alcance OAuth a través de
generateAccessToken. Solo granularidad a nivel de API.kubectl: Tokens de ServiceAccount de Kubernetes vinculados a roles RBAC mínimos. Los clústeres EKS y GKE pueden usar la reducción de privilegios dinámica del proveedor de nube subyacente; ver docs/KUBECTL_DOWNSCOPING.md.
Dos modos de aplicación
Modo 1 — Gancho Bash (herramientas CLI)
Un gancho PreToolUse intercepta cada llamada a la herramienta Bash. Si el comando comienza con un binario de servicio conocido (gh, gcloud, aws, kubectl), el gancho compara los argumentos con tus reglas YAML, evalúa la acción y reescribe el comando con un token con privilegios reducidos o emite un mensaje de bloqueo. Claude nunca ve la reescritura.
Modo 2 — Proxy MCP
Un proxy MCP envuelve un servidor MCP ascendente. Antes de reenviar cada llamada a la herramienta, aplica las mismas reglas YAML para inyectar el token con privilegios reducidos para esa herramienta específica. Actualmente es compatible con el servidor github-pr-issue-analyser; otros servidores son una extensión futura.
Inicio rápido
1. Instalar
pip install -e .2. Configurar credenciales
Exporta los tokens con privilegios reducidos en tu perfil de shell o entorno 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. Crear un archivo de política
cp config.example.yaml .claude/downscoping.yamlEdítalo para que coincida con el modelo de acceso de tu organización. El campo downscope_mode selecciona el mecanismo por servicio:
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. Registrar el gancho
Añádelo al archivo .claude/settings.json de tu proyecto:
{
"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. (Opcional) Habilitar el proxy MCP
Añádelo a .mcp.json en la raíz de tu proyecto:
{
"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"
}
}
}
}Referencia del archivo de política
Acciones de regla
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 manuallyEl orden de las reglas importa: las reglas se evalúan de arriba a abajo; la primera coincidencia gana. Coloca las reglas específicas de deny/review antes de las reglas generales de allow.
Orden de resolución de tokens (modo token_slot)
Lee
env_vardel entorno del proceso actualSi no está configurado, vuelve a la variable
inject_as(utiliza la credencial ambiental)Si ninguno está configurado, pasa el comando sin modificar
Arquitectura
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 serverServicios soportados
Servicio | Binario / Interfaz | Modo de reducción | Doc |
GitHub CLI |
| token_slot | |
AWS CLI |
| sts_policy (preferido), token_slot | |
Google Cloud |
| credential_access_boundary (GCS), oauth_scope, token_slot | |
Kubernetes |
| token_slot; EKS/GKE dinámico (futuro) | |
Servidores MCP | proxy | token_slot |
Se pueden añadir servicios adicionales extendiendo config.yaml: no se requieren cambios de código.
Notas de seguridad
Los valores de los tokens se escapan con
shlex.quoteantes de la inyección en el shell para evitar la inyección de comandos a través de valores de token manipulados.Anteponer
TOKEN=valueantes de un comando hace que el token sea visible en los listados de procesos (ps aux). Para entornos de mayor seguridad, utiliza un ayudante de credenciales que inyecte tokens a través de un descriptor de archivo o un gestor de secretos.Los mensajes de bloqueo incluyen el nombre de la regla y el patrón coincidente para que el motivo sea siempre auditable.
La alternativa al token ambiental
inject_assignifica que si aún no has aprovisionado un token con privilegios reducidos, los comandos pasan utilizando la credencial ambiental. EstableceDOWNSCOPE_REQUIRE_SCOPED=1(futuro) para endurecer esto..claude/settings.jsonque contiene rutas locales debe ser ignorado por git: consulta.gitignoreen este repositorio.
Desarrollo
pip install -e .
pytest tests/Licencia
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