Credenciales y el límite de red

Una sesión de codificación agéntica necesita credenciales: una clave de Anthropic para hablar con Claude, un token de GitHub para hacer push, claves de AWS para desplegar. También ejecuta código arbitrario, instala paquetes arbitrarios y sigue instrucciones de archivos que no escribió. Entregar a un entorno así tus secretos reales es la forma en que las claves acaban en la bandeja de entrada de un ladrón.

Bromure Agentic Coding resuelve esta tensión con el límite de red: el agente dentro de la VM solo ve tokens señuelo falsos. Tus credenciales reales viven cifradas en el anfitrión macOS y son sustituidas en la red por un proxy MITM del lado del anfitrión en el último momento posible: después de que la solicitud haya salido de la VM, y solo cuando va destinada al anfitrión al que pertenece la credencial. Ningún archivo, variable de entorno ni proceso dentro de la VM contiene jamás una clave de API real, un token OAuth, un secreto de AWS o una clave privada SSH.

Este capítulo explica el mecanismo de principio a fin, y luego recorre cada tipo de credencial admitido y su ciclo de vida, el sistema de aprobación por uso, el detector de compromiso y cómo verificar el límite tú mismo.

Nota: Este capítulo cubre los conceptos y el comportamiento en tiempo de ejecución. Para una referencia campo por campo del panel de ajustes, consulta Ajustes → Credenciales.

El límite de red de un vistazo

Tres principios definen el modelo:

  1. Señuelos en la VM. Cada credencial que configuras es reemplazada dentro de la VM por un señuelo que preserva su estructura. Los señuelos mantienen la forma que esperan los validadores —un señuelo de Anthropic empieza por sk-ant-api03-brm-, un señuelo de GitHub es ghp_ más 36 caracteres—, de modo que herramientas como claude, gh y doctl los aceptan sin quejas.
  2. Reales solo en la red. Cada solicitud HTTPS que hace la VM se tuneliza al proxy del anfitrión, que la descifra, cambia el señuelo por el valor real y vuelve a cifrar aguas arriba. El cambio se limita al anfitrión de destino para el que se acuñó la credencial.
  3. Fallo cerrado. Si algo elude el proxy, la solicitud lleva solo un señuelo y la autenticación aguas arriba falla. No hay ninguna vía por la que un secreto real se filtre por accidente.

Los señuelos son deterministas: cada uno se deriva del valor real más una sal de 32 bytes por instalación mediante HKDF-SHA256. La misma clave real siempre se corresponde con el mismo señuelo en tu Mac, de modo que los clientes que toman la huella de su clave (Claude Code guarda en caché un hash de clave, por ejemplo) nunca ven que la credencial «rote» entre sesiones.

CredencialForma del señuelo en la VM
Clave de API de Anthropicsk-ant-api03-brm-…
Clave de API de OpenAIsk-brm-…
Clave de API de xAIxai-brm-…
Token de GitHubghp_ + 36 caracteres (40 en total)
Token de GitLabglpat- + 20 caracteres
PAT de DigitalOceandop_v1_ + hex (64 caracteres en total)
Clave de API de Linearlin_api_ + 40 caracteres (48 en total)
Token bearer de MCPbrm-mcp_…
Contraseña de registro Dockerbrm-docker-… (al menos 40 caracteres)
Token bearer de Kubernetesbrm-k8s-…
Secreto de base de datosbrm-db-… (al menos 32 caracteres)
Token manual genéricobrm_…

No hay ningún interruptor de encendido/apagado para el límite. El proxy es la única vía de salida de la VM; el cambio es simplemente cómo funcionan las credenciales en esta app.

Cómo funciona el cambio de principio a fin

El recorrido completo de ida y vuelta de una solicitud autenticada:

  1. Lanzamiento de sesión: el plan de tokens. Cuando arranca la VM de un espacio de trabajo, la app construye un plan de tokens por espacio de trabajo que empareja cada credencial real con su señuelo derivado. Los señuelos se escriben en la VM: variables de entorno (ANTHROPIC_API_KEY, GH_TOKEN, LINEAR_API_KEY, …) y archivos de configuración (~/.git-credentials, ~/.docker/config.json, ~/.kube/config, ~/.aws/config, ~/.config/doctl/config.yaml, configuraciones de MCP). Los valores reales se cargan en el mapa de cambio en memoria del proxy, cada uno indexado por el anfitrión de destino al que pertenece.
  2. La solicitud sale de la VM. El tráfico HTTPS del invitado se tuneliza sobre un socket virtio (vsock puerto 8443) al proxy del anfitrión. La VM no tiene ninguna otra ruta a la red.
  3. Terminación TLS. El proxy presenta un certificado hoja por anfitrión falsificado —el nombre de anfitrión de destino como CN y SAN, una clave EC por anfitrión— firmado por la Bromure Agentic Coding Root CA. Como el certificado público de esa CA se instaló en el almacén de confianza de la VM en el arranque, los clientes TLS del invitado aceptan la conexión y el proxy puede leer la solicitud en texto plano.
  4. El cambio. El proxy busca cada token señuelo que aparece en la solicitud (encabezados, y para los tipos de credencial que lo activan, el cuerpo) y, si el anfitrión de destino coincide con el alcance de la credencial, lo reemplaza por el valor real.
  5. Recifrado aguas arriba. La solicitud reescrita se vuelve a emitir al destino real mediante URLSession de Apple, es decir, la propia pila TLS de macOS, que valida el certificado genuino del servidor aguas arriba. La respuesta fluye de vuelta a través del túnel hacia el invitado.

Si el destino no coincide con el alcance de un señuelo, el señuelo sale sin cambios (y falla la autenticación aguas arriba) o, cuando la discrepancia parece exfiltración, la solicitud se bloquea de plano (consulta El detector de compromiso más abajo).

La Bromure Agentic Coding Root CA

La CA es por instalación y reside en ~/Library/Application Support/BromureAC/ca/ (cert.pem más un key.pem con modo 0600). Su sujeto es «Bromure Agentic Coding Root CA», organización «Bromure». Propiedades que conviene conocer:

  • La validez de la CA es de 10 años. Los certificados hoja por anfitrión falsificados son válidos durante 1 año y están antedatados 24 horas, de modo que un invitado cuyo reloj se desvió durante la suspensión/reanudación aún los acepta. Las hojas se guardan en caché por anfitrión durante la vida del proceso de la app.
  • El certificado público se instala en el almacén de confianza de cada VM en el arranque (entregado a través del recurso compartido meta y aplicado con update-ca-certificates). Nunca sale de tu máquina y no es de confianza para nada excepto tus VM.
  • Para rotar la CA, cierra la app y elimina el directorio ca/. Se acuña una CA nueva en el siguiente lanzamiento y cada VM recoge el nuevo certificado público en su siguiente arranque. La rotación no invalida nada más: los secretos del espacio de trabajo y los metadatos de profile.json quedan intactos.

Alcance por anfitrión

Cada entrada de cambio está vinculada a un alcance de anfitrión. La coincidencia es exacta o de subdominio y no distingue mayúsculas de minúsculas, nunca por subcadena: una credencial con alcance openai.com coincide con api.openai.com pero no con openai.com.evil.example —un anfitrión que imita el aspecto no puede engañar al proxy para que decore su solicitud con una clave real—. Las reglas de token manual pueden usar deliberadamente un filtro de anfitrión en blanco, lo que significa «inyectar en cualquier anfitrión»; esa es una elección explícita que haces por entrada (consulta Claves de API genéricas).

Fallo cerrado por construcción

El diseño nunca depende de que el proxy sea inevitable para la confidencialidad: depende de que los secretos no estén allí:

  • Una solicitud que de algún modo salta el proxy lleva un token señuelo; la API aguas arriba lo rechaza.
  • Las solicitudes de AWS firmadas dentro de la VM se firman con una clave secreta señuelo; si llegaran a AWS directamente fallarían con InvalidSignatureException (consulta AWS más abajo).
  • Los bytes de la clave privada SSH nunca están en la VM en absoluto; solo las firmas cruzan el límite.

Gestión de credenciales en el editor del espacio de trabajo

Las credenciales se configuran por espacio de trabajo. Abre el editor del espacio de trabajo (Editar espacio de trabajo) y selecciona Credenciales en la barra lateral.

El panel de Credenciales del editor del espacio de trabajo, mostrando los campos de Identidad de Git sobre la lista de credenciales configuradas, un botón Añadir credencial y un botón Importar archivo env

El panel se abre con Identidad de Git (un nombre y un correo electrónico escritos en ~/.gitconfig en la VM; deja ambos en blanco para conservar los valores predeterminados de git —los marcadores de posición son solo ejemplos, no credenciales—), seguidos de una lista únicamente de las credenciales que has configurado, agrupadas bajo encabezados de categoría (Agentes, Git, Nube, Bases de datos, SSH, Otros). Dos botones se ubican en la parte inferior: Añadir credencial abre un selector de los tipos de credencial —token de Git, clave SSH, credenciales de AWS, token de DigitalOcean, clave de API de Linear, Kubernetes, registro de contenedores, base de datos y Otra clave de API— e Importar archivo env… importa en bloque desde un .env o un ~/.bashrc. La propia clave del agente principal reside en el panel Agentes, descrito a continuación. Haz clic en Guardar; el siguiente lanzamiento de sesión escribe los señuelos en la VM y carga los reales en el proxy.

La barrera de aprobación por credencial (Preguntar antes de usar) y la política de escritura de cada servicio se configuran en el panel Salvaguardas, no aquí: el panel de Credenciales ya no incluye esos controles. Consulta Ajustes → Credenciales para la referencia campo por campo.

Seis proveedores se gestionan automáticamente —Anthropic, OpenAI, GitHub, GitLab, DigitalOcean y Kubernetes no necesitan reglas de token manual; sus secciones dedicadas los cubren—. Todo lo demás pasa por Otras claves de API.

Importar desde un archivo env. Importar archivo env… lee un archivo .env existente —o un ~/.bashrc— y convierte sus variables en credenciales. El analizador maneja KEY=VALUE y export KEY=VALUE, elimina las comillas circundantes y los comentarios finales, y omite deliberadamente cualquier cosa que necesitaría evaluación de shell (interpolación $VAR o sustitución $(…)), por lo que es seguro apuntarlo a un .bashrc real. Una hoja de revisión muestra entonces las variables con valores enmascarados: los nombres reconocidos (ANTHROPIC_API_KEY, OPENAI_API_KEY, XAI_API_KEY, GH_TOKEN/GITHUB_TOKEN, GITLAB_TOKEN, AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN, DIGITALOCEAN_ACCESS_TOKEN, LINEAR_API_KEY) se asignan automáticamente a su tipo de credencial, mientras que los nombres no reconocidos pueden importarse como tokens manuales genéricos con un alcance de anfitrión separado por comas que tú proporcionas. Las entradas ya configuradas se marcan y se dejan sin seleccionar para que una reimportación nunca sobrescriba un secreto en silencio.

Tipos de credenciales

Claves de API del agente principal (Anthropic, OpenAI, xAI)

La clave del agente principal del espacio de trabajo se configura en el panel Agentes, donde cada tarjeta de agente ofrece un selector de modo de autenticación.

El panel de Agentes mostrando la tarjeta de Claude Code marcada como Principal, con los modos de autenticación token de API, Suscripción (inicio de sesión interactivo) con un enlace Registrar…, Bedrock (AWS) y una opción de Modelo local desactivada, además de un campo de clave de API de Anthropic

Elige token de API y pega la clave en el campo (Clave de API de Anthropic para Claude Code, Clave de API de OpenAI para Codex, la clave de xAI para Grok Build). Ciclo de vida:

  • En la VM: exportada como ANTHROPIC_API_KEY / OPENAI_API_KEY / XAI_API_KEY, conteniendo el señuelo con la forma del proveedor (sk-ant-api03-brm-…, sk-brm-…, xai-brm-…).
  • En la red: cambiada por la clave real en las solicitudes a los anfitriones del proveedor (anthropic.com, openai.com, x.ai respectivamente).
  • Aprobación: para controlar el primer uso de cada sesión, activa Preguntar antes de usar para la clave del agente en el panel Salvaguardas (consulta Aprobación por uso). Está desactivada de forma predeterminada.

Los otros modos de autenticación del selector —Suscripción (inicio de sesión interactivo), Bedrock (AWS) y Modelo local— se cubren más abajo y en Modelos locales. Desde la CLI, la misma elección es --auth token|subscription|bedrock|local en bromure-cli workspaces create (y token|subscription|bedrock en bromure-cli vm run para espacios de trabajo sobre la marcha).

Suscripciones de Claude, Codex y Grok

Si tienes una suscripción de Claude, ChatGPT (Codex) o Grok en lugar de una clave de API, el agente normalmente se autentica mediante inicio de sesión OAuth interactivo: un flujo de navegador que una VM en entorno aislado no puede (ni debe) completar con tokens reales. Bromure Agentic Coding admite suscripciones con dos mecanismos. Ambos terminan en el mismo lugar: los tokens OAuth reales viven solo en el anfitrión, y el invitado se ejecuta con una clave falsa.

Registrar con Claude / ChatGPT / Grok (recomendado)

Configura el modo de autenticación del agente en Suscripción (inicio de sesión interactivo) y haz clic en Registrar…. Lo que sucede:

  1. La app comprueba que el proxy está en ejecución (de lo contrario se rechaza el registro) y muestra una hoja explicativa titulada Registrar con Claude (o ChatGPT / Grok). Haz clic en Continuar.
  2. Arranca una VM de registro desechable —temporal, aislada, sin montajes de carpetas del espacio de trabajo y sin mapa de cambio de credenciales—. Dentro de ella se ejecuta el comando de inicio de sesión real (claude login, codex login o el equivalente de Grok).
  3. El navegador predeterminado de tu Mac abre la página de inicio de sesión del proveedor. Inicia sesión como de costumbre. Tienes unos 4 minutos antes de que el flujo caduque.
  4. Los tokens OAuth resultantes se capturan en el anfitrión, se cifran y se almacenan; la VM desechable se destruye.
  5. Si lanzaste el registro desde un editor de espacio de trabajo, la app pregunta ¿Compartir con todos los espacios de trabajo?: elige Todos los espacios de trabajo para almacenar la suscripción como el valor predeterminado compartido, o Solo este espacio de trabajo. El registro iniciado desde las Preferencias de la app siempre almacena el valor predeterminado compartido sin preguntar.

A partir de entonces, el invitado de cada sesión se ejecuta en modo de clave de API con una credencial falsa determinista: una ANTHROPIC_API_KEY falsa para Claude, un ~/.codex/auth.json sembrado que contiene un JWT falso con caducidad muy lejana en el futuro para Codex (de modo que el cliente nunca intente refrescarlo por sí mismo), un ~/.grok/auth.json de marcador de posición para Grok. El proxy reconoce el valor falso e inyecta un token de acceso Authorization: Bearer en vivo (más el encabezado beta de OAuth, para Claude) en la red.

La custodia y el refresco de tokens son enteramente del lado del anfitrión. El anfitrión refresca los tokens unos 5 minutos antes de la caducidad contra el endpoint de tokens del proveedor (platform.claude.com/v1/oauth/token para Claude, auth.openai.com/oauth/token para Codex, auth.x.ai/oauth2/token para Grok), de modo que un solo refresco sirve para cada VM en ejecución y el invitado nunca posee un token de refresco. Un registro recién capturado se almacena deliberadamente con una caducidad ya pasada, forzando un refresco en el primer uso, lo que demuestra que la vía de refresco funciona antes de que dependas de ella.

Los controles junto al selector de modo de autenticación completan el ciclo de vida: Volver a registrar… repite la captura (por ejemplo, tras revocar sesiones aguas arriba), y Olvidar elimina la suscripción almacenada del anfitrión.

El cambio de token en sesión

Alternativamente, si el agente inicia sesión él mismo dentro de la VM (ejecutas claude login en la sesión), el proxy detecta un token OAuth de suscripción real dirigiéndose al proveedor y se ofrece a tomar su custodia. Aparece una hoja —¿Cambiar el token de suscripción de Claude? (o Codex)— que explica que el token real puede quedarse en este Mac mientras un señuelo lo reemplaza en el archivo de credenciales de la VM. Tanto el token de acceso como el de refresco se cambian juntos. Tus opciones:

BotónEfecto
CambiarLos tokens reales se trasladan al almacén del anfitrión; el archivo de credenciales de la VM se reescribe con señuelos; el proxy inyecta el token real en la red a partir de ahora.
Ahora noNada cambia en esta sesión; el aviso vuelve en la siguiente sesión.
Nunca para este espacio de trabajoDetiene los avisos para este espacio de trabajo.

El estado por espacio de trabajo detrás de este aviso es visible en el editor como Cambio de token de suscripción de Claude / Cambio de token de suscripción de Codex (sin establecer de forma predeterminada; «aceptado» o «rechazado» después de que elijas). El canal de cambio anfitrión-a-VM es deliberadamente unidireccional: el anfitrión solo puede escribir señuelos en la VM, y la VM solo puede enviar reales al anfitrión —no existe ninguna RPC por la que la VM pueda pedir un token real de vuelta—. El agente dentro de la VM además se niega a escribir cualquier credencial que no lleve el prefijo señuelo brm-, de modo que ni siquiera un anfitrión con mal comportamiento puede corromper el archivo de credenciales del invitado con un valor real.

Nota: Codex permanece en modo de suscripción dentro del invitado (su modo de clave de API apunta a un backend diferente), y los tokens de Grok viajan a través del archivo ~/.grok/auth.json en lugar de un agente vsock. Estos son detalles de implementación; el modelo de custodia es idéntico.

AWS

AWS recibe el tratamiento más profundo de cualquier proveedor, porque las solicitudes de AWS no se autentican mediante un token bearer: se firman (SigV4). Abre Credenciales → AWS en el editor del espacio de trabajo; un control segmentado elige entre Claves estáticas y SSO / Identity Center.

Claves estáticas y el refirmador del anfitrión

Pega tu ID de clave de acceso y tu Clave de acceso secreta (más un Token de sesión STS opcional y una Región predeterminada). El ciclo de vida:

  • En la VM: ~/.aws/config apunta a un asistente credential_process que suministra —sobre vsock puerto 8445— el ID de clave de acceso real emparejado con una Clave de acceso secreta señuelo de 40 caracteres, omitiendo el token de sesión. Cada SDK de AWS, la CLI aws, terraform y boto3 lo recogen de forma nativa; no se necesita configuración específica de herramienta.
  • Lo que hace el invitado: firma sus solicitudes con el secreto señuelo, produciendo una firma SigV4 sintácticamente válida pero criptográficamente condenada al fracaso.
  • En la red: el refirmador de AWS del anfitrión detecta las solicitudes destinadas a *.amazonaws.com y *.amazonaws.com.cn (incluidos los anfitriones GovCloud, ISO, regionales y S3 de estilo bucket), elimina la firma del invitado, inyecta el X-Amz-Security-Token real cuando hay un token de sesión presente, y vuelve a firmar con el secreto real antes de que la solicitud salga de tu Mac. Cada refirma exitosa emite un evento de auditoría credential.aws_sign con una clave de acceso enmascarada, visible en Trazado.

Esto es de fallo cerrado en el sentido más fuerte: la clave secreta real nunca existe en la VM de ninguna forma, y una solicitud que elude el proxy es rechazada por AWS con InvalidSignatureException.

Tres estilos de solicitud no son compatibles y devuelven un error claro al invitado en lugar de un fallo silencioso: subidas de S3 con streaming por fragmentos (STREAMING-AWS4-HMAC-SHA256-PAYLOAD, respondidas con 501), firma asimétrica SigV4A y URL prefirmadas de cadena de consulta (que incrustan la firma donde el refirmador no puede reemplazarla).

SSO / IAM Identity Center

Si tu organización usa IAM Identity Center, selecciona SSO / Identity Center en lugar de pegar claves de larga duración:

  1. Haz clic en Conceder acceso a ~/.aws y aprueba el aviso de acceso a la carpeta (una concesión con alcance de seguridad; la carpeta se lee en el anfitrión y nunca se monta en la VM).
  2. Elige tu perfil en el selector de perfil SSO. La app descubre las secciones [profile …] en ~/.aws/config que llevan sso_start_url, sso_account_id y sso_role_name, resolviendo las referencias [sso-session …]; el ID de cuenta y el rol se muestran de solo lectura.
  3. Al iniciar la sesión, el anfitrión resuelve las credenciales temporales del rol desde la caché de tokens SSO (~/.aws/sso/cache). Si el token en caché ha caducado, tu navegador se abre para aws sso login, ejecutado en el anfitrión, desde /usr/local/bin/aws.

Las claves temporales resueltas alimentan el mismo refirmador que las claves estáticas; la VM sigue sin ver nunca un secreto. Las credenciales se refrescan automáticamente en el anfitrión unos 5 minutos antes de caducar.

Bedrock

Bedrock (AWS) en el selector de modo de autenticación del agente ejecuta Claude Code contra AWS Bedrock usando las credenciales de AWS que tenga configuradas el espacio de trabajo (estáticas o SSO): es un modo de autenticación de la herramienta principal, no una credencial separada. Configura el modo de autenticación, configura Credenciales → AWS y, opcionalmente, establece un ID de modelo de Bedrock en el espacio de trabajo. La firma pasa por la misma vía del refirmador, ya que los endpoints de Bedrock son anfitriones *.amazonaws.com.

Tokens HTTPS de Git (GitHub, GitLab, Bitbucket, autoalojado)

Los tokens de acceso personal para git-sobre-HTTPS residen en Tokens de GitHub / Tokens de GitLab / Tokens de Bitbucket (colectivamente, tokens HTTPS). Cada entrada toma un anfitrión, un nombre de usuario y el token; las instancias autoalojadas de GitLab o Gitea funcionan estableciendo el campo de anfitrión. Ciclo de vida:

  • En la VM: se escribe un señuelo en ~/.git-credentials y en la configuración de gh/glab; GH_TOKEN y GITLAB_TOKEN se exportan para que las CLI se autentiquen automáticamente. Las formas de los señuelos coinciden con los validadores de cada proveedor (ghp_ + 36 para GitHub, glpat- + 20 para GitLab, brm_… en los demás casos), de modo que las comprobaciones de prefijo y longitud en gh y glab pasan.
  • En la red: cambiado por el token real en las solicitudes al anfitrión git de esa entrada.
  • Aprobación: cada entrada obtiene su propia fila Preguntar antes de usar en el panel Salvaguardas.

Si solo necesitas git push sobre SSH, es posible que no necesites ningún token HTTPS en absoluto: consulta Claves SSH más abajo.

Claves de API genéricas (Otras claves de API / Reglas de token manual)

Para cualquier API que la app no gestione automáticamente, añade una entrada en Otras claves de API (las reglas de token manual, que también aparecen como Cambio de token MITM). Haz clic en Añadir token y proporciona:

CampoSignificado
NombreUna etiqueta para la entrada.
ValorEl secreto real (almacenado cifrado en el anfitrión).
Nombre de variable de entornoLa variable bajo la que se exporta el señuelo dentro de la VM. Referénciala desde tu código.
Filtro de anfitrión (opcional)El alcance de anfitrión para el cambio.

Dos casos límite son deliberados:

  • Nombre de variable de entorno vacío: no se exporta nada; copias el señuelo del banner de bienvenida de la sesión y lo colocas donde tu utillaje lo necesite.
  • Filtro de anfitrión en blanco: el valor real se inyecta en cualquier anfitrión, sin preguntar. Esa es una elección explícita de siempre activo —útil para APIs con muchos nombres de anfitrión regionales—, pero significa que el alcance de la credencial ya no la protege. Para controlar un secreto sin alcance, activa Preguntar antes de usar para él en el panel Salvaguardas (o dale un filtro de anfitrión después de todo).

Anthropic, OpenAI, GitHub, GitLab, DigitalOcean y Kubernetes nunca necesitan entradas manuales aquí.

Referencias de secretos de 1Password (op://)

En lugar de pegar un secreto real, el valor de una Otra clave de API puede ser una referencia de secreto de 1Passwordop://vault/item/field, o la forma con llaves {{ op://vault/item/field }} que usan op inject y los archivos .env.op—. Solo se almacena en disco la referencia; el secreto en sí nunca se escribe en ninguna parte del anfitrión ni de la VM. El editor reconoce la referencia, la muestra en claro (no es un secreto) y señala que se resuelve a través de 1Password.

En cada lanzamiento del espacio de trabajo, Bromure resuelve la referencia del lado del anfitrión con la CLI de 1Password (op read), acuña un señuelo a partir de la cadena de referencia (de modo que el señuelo permanezca estable incluso cuando el secreto rota) y exporta solo ese señuelo a la VM. El proxy MITM cambia entonces el señuelo por el valor resuelto en la red, exactamente como lo hace con un secreto pegado, y vuelve a resolver cada 2 minutos, de modo que rotar el elemento en 1Password surte efecto en un par de minutos sin reiniciar.

Esto necesita la CLI op instalada y con sesión iniciada —desbloqueo biométrico a través de la app de 1Password, o op signin en un terminal—. Si no se encuentra op, el editor muestra un enlace Obtener la CLI de 1Password y el espacio de trabajo muestra las instrucciones de instalación al lanzarse; si la resolución falla (sin sesión iniciada, o el elemento no existe), Bromure muestra el error para que puedas corregirlo y reiniciar el espacio de trabajo.

Importar un archivo .env o .env.op (Importar desde .env… en el editor) reconoce los valores op:// automáticamente —bajo nombres reconocidos como ANTHROPIC_API_KEY o arbitrarios como STRIPE_KEY— y almacena cada uno como un token manual que contiene la referencia.

DigitalOcean

Pega un token de acceso personal en Credenciales → DigitalOcean (el enlace Abrir la página de tokens de DigitalOcean en tu navegador te lleva a la generación de tokens). El señuelo (dop_v1_ + hex, 64 caracteres) se exporta como DIGITALOCEAN_ACCESS_TOKEN y se escribe en ~/.config/doctl/config.yaml, de modo que doctl auth init es innecesario. El cambio cubre las solicitudes a digitalocean.com, más una segunda entrada para el blob de autenticación Basic en base64 usado por docker login / doctl registry login contra registry.digitalocean.com, de modo que los push y pull del registro también se resuelven.

Linear

Pega una clave de API personal en Credenciales → Linear (enlace: Abrir los ajustes de API de Linear en tu navegador; las claves provienen de linear.app → Ajustes → API). El señuelo (lin_api_ + 40) se exporta como LINEAR_API_KEY, que el SDK de Linear, los servidores MCP y las herramientas de CLI recogen automáticamente; el cambio se limita estrictamente a linear.app (GraphQL en api.linear.app y MCP en mcp.linear.app). Una clave de Linear en el espacio de trabajo es también el requisito previo para los disparadores de automatización de incidencias de Linear: consulta Automatización y CLI.

Tokens bearer de servidores MCP

Los servidores MCP de transporte HTTP configurados en el panel MCP reciben el mismo tratamiento: el token bearer real se queda en el anfitrión, un señuelo brm-mcp_… se inyecta en la configuración de MCP que lee el agente, y el proxy lo cambia en la red, limitado al anfitrión del servidor. Solo los servidores de transporte HTTP habilitados con un token bearer no vacío reciben una entrada de cambio.

Una cortesía adicional: para los anfitriones con una entrada brm-mcp_, el proxy responde a las rutas de descubrimiento OAuth/OIDC (los endpoints .well-known de servidor de autorización, recurso protegido y configuración de OpenID) con 404. Claude Code trata entonces al servidor como preautenticado en lugar de intentar su propio flujo OAuth, que de todos modos nunca podría completarse dentro de la VM.

Registros de contenedores (Docker Hub, GHCR y afines)

Credenciales → Registros de contenedores gestiona la autenticación HTTP Basic para docker pull/push. Existen preajustes para Docker Hub (docker.io), GitHub Container Registry (ghcr.io) y GitLab Container Registry (registry.gitlab.com); cualquier otro registro puede añadirse por anfitrión. Ciclo de vida:

  • En la VM: ~/.docker/config.json contiene un blob de autenticación señuelo —el base64 de tu nombre de usuario emparejado con una contraseña derivada brm-docker-…—, de modo que Docker cree que ha iniciado sesión.
  • En la red: el proxy sustituye el blob base64 real en el anfitrión de registro coincidente. La danza de tokens de la especificación de distribución también se maneja: se añaden entradas de cambio para los realms de autenticación conocidos (Docker Hub se autentica contra auth.docker.io, el registro de DigitalOcean contra api.digitalocean.com).
  • Importar: haz clic en Importar config.json… para extraer entradas de un ~/.docker/config.json existente en el anfitrión. Las entradas delegadas a credsStore/credHelpers se omiten —sus contraseñas viven en el llavero del sistema operativo, no en el archivo— y el resumen de importación informa cuántas se omitieron y por qué.
  • Aprobación: por registro, mediante Preguntar antes de usar en el panel Salvaguardas. Eliminar este registro borra una entrada.

Contextos de Kubernetes

Credenciales → Kubernetes convierte los contextos de kubeconfig en acceso al clúster mediado por proxy. Haz clic en Importar kubeconfig para analizar un kubeconfig existente en una fila por contexto (el contexto actual primero, el tipo de autenticación detectado automáticamente), o Añadir contexto para introducir manualmente una URL de servidor, credenciales, espacio de nombres y CA del clúster. En todos los casos la VM recibe un ~/.kube/config sintético: kubectl en el invitado habla con el proxy (de confianza a través de la CA de Bromure), nunca directamente con el servidor de API.

Por tipo de autenticación:

  • Los contextos de token bearer reciben un marcador de posición brm-k8s-… en la VM, cambiado por el token real en la red.
  • Los contextos de certificado de cliente reciben un certificado y una clave autofirmados desechables en la VM; el certificado y la clave reales se registran en el anfitrión como una SecIdentity y se usan para mTLS aguas arriba.
  • Los contextos de plugin exec nunca ejecutan el plugin en la VM en absoluto. El sondeador de plugin exec ejecuta el comando en el anfitrión en cada intervalo de refresco (predeterminado 600 segundos, mínimo 60), analiza el JSON de ExecCredential y alimenta el token fresco al mapa de cambio. Los refrescos preservan el estado de consentimiento de la entrada.

Si el kubeconfig suministra la propia CA del clúster, se reenvía para que el proxy pueda verificar el servidor de API aguas arriba. Los campos de ruta de archivo en un kubeconfig importado (CA, cert, clave) se leen con avidez en el momento de la importación —los cambios posteriores a esos archivos en disco no se recogen—. Cada contexto obtiene su propia fila Preguntar antes de usar en el panel Salvaguardas, donde una política de escritura puede además eliminar verbos destructivos (kubectl delete, Delete*/Terminate* de AWS, docker push, git push) del lado del anfitrión antes de que se reenvíe un solo byte —una capa separada del cambio de credenciales—.

Bases de datos HTTP (MongoDB, ClickHouse, Elasticsearch)

Credenciales → Bases de datos (las secciones de MongoDB / ClickHouse / Elasticsearch) cubre los endpoints de base de datos que hablan HTTPS —la Data API de Mongo, la interfaz HTTP de ClickHouse, Elastic—. Cada endpoint toma un motor, un anfitrión, un secreto, un nombre de usuario, un tipo de autenticación y uno o más nombres de variables de entorno (separados por comas) bajo los que se exporta el señuelo brm-db-…; referencia esas variables desde tu código o cadenas de conexión.

Las credenciales de base de datos son la única familia en la que el cambio barre el cuerpo de la solicitud además de los encabezados y los parámetros de consulta, porque los secretos de conexión viajan habitualmente dentro de cargas JSON o SQL. El proxy parchea Content-Length tras un cambio de cuerpo; los cuerpos multipart o binarios no relacionados de otro tráfico nunca se tocan (todos los demás cambios se limitan a los encabezados). Los endpoints de autenticación Basic también reciben el cambio de su blob base64 de usuario y secreto. El Preguntar antes de usar por endpoint y la política de escritura se configuran en el panel Salvaguardas.

Claves SSH

SSH se maneja sin ningún token en absoluto: el SSH_AUTH_SOCK de la VM está respaldado por un puente ssh-agent sobre vsock (puerto 8444). El invitado puede listar identidades y solicitar firmas, pero los bytes de la clave privada viven solo en el anfitrión y físicamente no pueden leerse ni extraerse desde dentro de la VM. Existen dos fuentes de claves, ambas bajo Credenciales → Claves SSH:

  • La clave predeterminada por espacio de trabajo. Se genera un par de claves ed25519 predeterminado compartido al arrancar la app (almacenado bajo default-ssh/ en Application Support) y se copia en el directorio del agente de cada nuevo espacio de trabajo. El panel muestra la clave pública del espacio de trabajo para que puedas pegarla en tu anfitrión git (para GitHub: github.com/settings/keys). También puedes acuñar una clave nueva desde la CLI con bromure-cli workspaces ssh-keygen <workspace-id|name>, que imprime la nueva clave pública.
  • Claves importadas. Haz clic en Importar… / Importar archivo… bajo Claves SSH importadas y apunta la app a un archivo de clave privada existente —se admiten RSA, ed25519 y ECDSA, incluidas las claves cifradas—. Una clave cifrada solicita su frase de contraseña una vez en la importación; la frase de contraseña se almacena en el llavero de macOS (servicio io.bromure.agentic-coding.ssh-key-passphrases) y se suministra mediante SSH_ASKPASS en el lanzamiento, nunca se registra. La firma de claves importadas fluye a través de un proceso ssh-agent privado que la app genera para sí misma (ssh-agent -D en un socket bajo el directorio temporal) —separado de cualquier otra cosa en tu sistema—.

Por cada clave importada, activar Preguntar antes de usar en el panel Salvaguardas hace que cada solicitud de firma dentro de la VM pida consentimiento. Cada firma —clave predeterminada o importada— emite un evento de auditoría credential.ssh_sign que lleva la huella SHA256 de la clave y si era una clave gestionada o importada.

Nota: Tu ssh-agent de inicio de sesión de macOS (el de launchd) deliberadamente nunca se expone a la VM. Solo las claves por espacio de trabajo y las claves que importaste explícitamente son accesibles desde una sesión.

Aprobación por uso y duraciones de concesión

Cualquier credencial de este capítulo puede marcarse como Preguntar antes de usar —una casilla de verificación por credencial en el panel Salvaguardas (etiquetada Requerir aprobación para usar en el propio control), desactivada de forma predeterminada, descrita en la interfaz como: «Mostrar un diálogo de confirmación la primera vez que se usa esta credencial en una sesión.»—.

Cuando una credencial controlada se usa por primera vez en una sesión, el proxy retiene la solicitud y muestra un diálogo de consentimiento titulado ¿Permitir que «nombre del espacio de trabajo» use la credencial? (con el nombre de tu espacio de trabajo y la etiqueta de la credencial rellenados), ofreciendo cuatro botones:

BotónConcesión
Permitir durante 5 minutosLimitado en el tiempo; la credencial fluye sin más avisos durante 5 minutos.
Permitir durante 1 horaLimitado en el tiempo, 1 hora.
Permitir durante el resto de la sesiónHasta que se cierre la ventana de sesión.
No permitirLa solicitud se rechaza; la denegación se recuerda durante 5 minutos para que una tormenta de reintentos de un agente no produzca una tormenta de diálogos.

Comportamiento que conviene conocer:

  • Fusión. Las solicitudes concurrentes que necesitan la misma credencial se colapsan en un solo diálogo: un agente parlanchín que dispara doce llamadas de API en paralelo produce un solo aviso, y las doce siguen tu decisión.
  • La denegación gana. Una denegación en vivo cortocircuita antes de que se consulte cualquier permiso anterior.
  • Efímero por diseño. Las concesiones y denegaciones se mantienen solo en memoria y se revocan al desmontar la sesión. «Resto de la sesión» nunca sobrevive al cierre de una ventana, y nada se persiste entre ejecuciones de la app.
  • Sesiones sin interfaz. En una sesión SSH o sin interfaz, el aviso aparece en el tmux del espacio de trabajo en lugar de como una alerta gráfica: consulta Acceso remoto.

Para AWS, la barrera se aplica a cada llamada de firma del lado del anfitrión; para las claves SSH, a las solicitudes de firma; para todo lo demás, al primer cambio de red de la sesión.

Consejo: La barrera de consentimiento es por credencial, no por anfitrión. Si quieres que un token manual sin alcance permanezca bajo control, la aprobación es el mecanismo diseñado para ello.

La ventana de Aprobaciones de credenciales

Ventana → Aprobaciones de credenciales… abre una vista en vivo de cada decisión de consentimiento tomada durante la ejecución actual de la app: permisos limitados en el tiempo (5 minutos / 1 hora / resto de la sesión) y denegaciones recordadas. Cada fila muestra el nombre del espacio de trabajo y el tiempo restante, y ofrece Revocar; Revocar todo (⌘⌫) borra todo de una vez. La lista se actualiza automáticamente cada 2 segundos y se reduce naturalmente a medida que caducan las concesiones.

Como las decisiones son solo en memoria, la ventana está vacía después de que caduquen las concesiones, después de que se cierren las sesiones (concesiones con alcance de sesión) y después de que la app se cierre. Es un panel de control para el presente, no un registro de auditoría: para el historial, usa Trazado.

El detector de compromiso

Los señuelos cumplen una doble función: además de sustituir a los secretos, son trampas. Un token señuelo tiene exactamente una familia de destino legítima: el alcance de anfitrión para el que se acuñó. No hay ninguna razón honesta para que sk-ant-api03-brm-… aparezca en una solicitud a pastebin.example. Por eso el proxy escanea cada solicitud saliente —encabezados y cuerpo, mediante un autómata de Aho-Corasick, lo bastante barato para ejecutarse en todo— en busca de cualquier señuelo dirigido fuera de su alcance.

Cuando encuentra uno, trata la solicitud como un intento de exfiltración de credenciales:

  1. La solicitud se bloquea con HTTP 451. Ni un solo byte se reenvía al destino.
  2. La VM se pausa de inmediato.
  3. Se dispara una alerta: «Bromure detectó un intento saliente de filtrar una credencial de sesión a un anfitrión para el que no fue acuñada. La VM ha sido pausada.»

El espacio de trabajo se marca entonces como comprometido —el explorador de espacios de trabajo muestra Comprometido — al lanzarlo se pedirá borrar el disco y el home— y el siguiente lanzamiento requiere remediación: «Para continuar, la imagen de disco de la VM y la carpeta home persistente deben borrarse. Tus tokens, claves ssh y ajustes del espacio de trabajo se conservan.». Haz clic en Borrar y lanzar para continuar. Presta atención a la advertencia que la acompaña: las carpetas compartidas NO se borran, así que si el compromiso llegó a través de un paquete o archivo en una carpeta compartida, puede que aún esté allí —revisa esas carpetas antes de reanudar el trabajo—.

Respuesta recomendada ante una alerta de compromiso: abre el Inspector de trazas (⇧⌘I) o ejecuta bromure-cli trace leaks para ver el anfitrión y la solicitud infractores, decide si fue responsable una dependencia del proyecto o una instrucción inyectada por prompt (consulta Inyección de prompts y Cadena de suministro), luego borra y relanza.

Detalles de alcance:

  • Los señuelos sin alcance están exentos. Un token manual con un filtro de anfitrión en blanco es «cualquier anfitrión» por diseño y no puede disparar el detector; los marcadores de posición de suscripción falsos también quedan excluidos.
  • Los hermanos de primera parte se toleran. La coincidencia refleja la política de alcance del cambio, con una relajación: los anfitriones bajo el mismo dominio registrado que el proveedor de la credencial (la infraestructura de Claude o Codex bajo anthropic.com, por ejemplo) usan una coincidencia de familia, de modo que un token legítimo de api.anthropic.com visto en mcp-tools.anthropic.com no es una falsa alarma. Todo lo demás es estricto.
  • Las filtraciones de aspecto real también se marcan. Independientemente de las trampas de señuelo, el proxy marca los secretos sin cambiar, de aspecto real en el tráfico saliente —valores Bearer o x-api-key con prefijos conocidos (sk-ant-, ghp_, AKIA, …) o tokens opacos de 20 caracteres o más—. Estos aparecen como advertencias de filtración en el Inspector de trazas y en bromure-cli trace leaks; normalmente significan que un secreto real se pegó en la VM a mano, algo que el límite de red existe para hacer innecesario.

No hay nada que activar: el detector siempre está encendido.

Dónde viven los secretos en el anfitrión

Todo lo sensible se cifra en reposo con AES-GCM bajo una clave maestra de 256 bits por instalación —la bóveda de secretos—. La clave maestra vive en el Data Protection Keychain de macOS, limitada a la identidad de firma de la app, con accesibilidad kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly y sincronización con iCloud desactivada. Nunca pregunta, nunca sincroniza y nunca sale del Mac. Si el llavero es inalcanzable (una compilación sin firmar o sin aprovisionar), la app recurre a un archivo de clave con modo 0600 almacenado junto al texto cifrado —más débil, ya que la clave y el texto cifrado comparten entonces disco, pero mantiene el cifrado en reposo funcionando—; una versión totalmente aprovisionada usa el llavero.

Consecuencias prácticas:

  • Las copias de seguridad y las copias son texto cifrado. Una copia de seguridad de Time Machine o una carpeta Application Support copiada contiene solo blobs cifrados; sin la entrada del llavero de este Mac no pueden descifrarse (a menos que la clave de archivo de respaldo estuviera en uso y se copiara junto con ellos).
  • Borrar la entrada del llavero rota la clave. Los blobs cifrados existentes se vuelven ilegibles y vuelves a introducir tus credenciales. Los metadatos no sensibles en profile.json no se ven afectados.
  • Nada se sincroniza en ninguna parte. Ninguna credencial, almacén de tokens o material de clave es subido, sincronizado ni respaldado por la propia app.

Ubicaciones en disco, todas bajo ~/Library/Application Support/BromureAC/ salvo indicación:

UbicaciónContenido
ca/cert.pem, ca/key.pemLa Bromure Agentic Coding Root CA (clave en modo 0600). Elimina el directorio para rotar.
fake-salt.binLa sal HKDF de 32 bytes por instalación detrás de la derivación de señuelos (0600). Eliminarla rota cada señuelo en este Mac.
claude-subscription.enc, codex-subscription.enc, grok-subscription.encAlmacenes OAuth de suscripción cifrados con AES-GCM (predeterminado compartido más anulaciones por perfil), 0600.
secrets-master.keyLa clave maestra de respaldo con modo 0600 —presente solo cuando el Data Protection Keychain es inalcanzable—.
default-ssh/id_ed25519.raw, default-ssh/id_ed25519.pubEl par de claves SSH predeterminado compartido copiado en los nuevos espacios de trabajo.
profiles/<id>/ssh/Claves SSH acuñadas por espacio de trabajo (el directorio del agente).
Llavero: io.bromure.agentic-coding.master-keyLa clave maestra de la bóveda AES-256 (cuenta v1), Data Protection Keychain.
Llavero: io.bromure.agentic-coding.ssh-key-passphrasesFrases de contraseña de claves SSH importadas, un elemento por perfil/archivo de clave.

Las lecturas del lado del anfitrión para importaciones —~/.aws/config, ~/.aws/sso/cache/*.json, ~/.docker/config.json, archivos kubeconfig— ocurren solo en el anfitrión; ninguno de esos archivos se monta jamás en una VM. Los cuerpos de traza cifrados (consulta Trazado) usan la misma clave de bóveda.

Verificar el límite tú mismo

El límite de red está diseñado para ser comprobable, no aceptado por fe. Desde una shell dentro de cualquier sesión:

1. El entorno contiene señuelos.

echo "$ANTHROPIC_API_KEY"
# sk-ant-api03-brm-…            ← a fake, not your key

env | grep -E 'TOKEN|KEY' 
# every value is brm_/ghp_/glpat_/dop_v1_/lin_api_-shaped placeholder

2. Los archivos de configuración contienen señuelos.

cat ~/.git-credentials          # fake tokens per git host
cat ~/.docker/config.json       # fake base64 auth blobs
grep -A2 credential_process ~/.aws/config   # helper, not a secret key

3. Y aun así, todo funciona.

aws sts get-caller-identity     # succeeds — the host resigned the request
gh api user                     # succeeds — the fake was swapped on the wire

4. El TLS dentro de la VM termina en el proxy.

openssl s_client -connect api.anthropic.com:443 -brief 2>&1 | head
# issuer: the Bromure Agentic Coding Root CA — not a public CA

5. Las claves SSH están ausentes, pero la firma funciona.

ssh-add -L                      # lists public keys served by the vsock agent
ls ~/.ssh/id_*                  # no private key files to find

6. En el anfitrión, observa cómo ocurren los cambios. Habilita el trazado para el espacio de trabajo, luego:

bromure-cli trace summary        # per-request swap reports and leak warnings
bromure-cli trace leaks          # only the suspicious ones

o abre el Inspector de trazas (⇧⌘I), donde las solicitudes cambiadas se anotan como Nunca enviado a la VM — cambiado por el proxy.

Si alguna vez encuentras una credencial real dentro de una VM, llegó allí de una de dos maneras: tú (o el agente, bajo tu dirección) la pegaste a mano, o llegó a través de una carpeta compartida. La maquinaria de cambio nunca escribe reales en el invitado —y el detector de compromiso trata los secretos de aspecto real en la red como una filtración precisamente porque no deberían existir allí—.

Referencia rápida

Puertos vsock en el límite invitado-anfitrión:

PuertoPropósito
8443El proxy MITM HTTPS — toda la salida del invitado.
8444El puente ssh-agent detrás de SSH_AUTH_SOCK.
8445El asistente credential_process de AWS.
8446El agente de cambio de token de suscripción de Claude — un puerto que comparte con el puente de inferencia local (se configuran en flujos diferentes; ten esto en cuenta al diagnosticar una sesión que usa ambos — consulta Modelos locales).
8447El agente de cambio de token de suscripción de Codex (token de acceso, de refresco y de ID).

Comandos de CLI relacionados (referencia completa en Automatización y CLI):

ComandoPropósito
bromure-cli workspaces create --auth token|subscription|bedrock|localCrear un espacio de trabajo con su modo de autenticación.
bromure-cli vm run --auth token|subscription|bedrockIniciar una VM, seleccionando el modo de autenticación para un espacio de trabajo sobre la marcha.
bromure-cli workspaces ssh-keygen <workspace>Acuñar una clave SSH nueva del espacio de trabajo del lado del anfitrión e imprimir la clave pública.
bromure-cli trace summary [workspace]Resumir el tráfico trazado, incluidos los cambios y las advertencias de filtración.
bromure-cli trace leaks [workspace]Mostrar las solicitudes trazadas con posibles filtraciones de credenciales.