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 cómo inician sesión los agentes, cada tipo de credencial admitido y su ciclo de vida, el sistema de aprobación por uso, el detector de compromiso, las vías de escape para los hosts que fallan con la interceptación, y cómo verificar tú mismo el límite.

Las credenciales se configuran por máquina. Una máquina es lo que el editor de ajustes todavía llama espacio de trabajo; las dos palabras designan la misma VM y sus ajustes.

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. Las claves de API y las suscripciones de los agentes ya no se configuran en ese panel; están en Preferencias › Modelos (consulta Modelos y proveedores).

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-…
Clave de API de Moonshot (Kimi)sk-kimi-brm-…
Clave de OpenRouter usada por Claude Codesk-or-v1-brm-…
Clave de API de Amazon Bedrockbedrock-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 de autenticación de Twilio / secreto de clave de APIbrm-twilio-… (al menos 32 caracteres)
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. Inicio de la sesión — el plan de tokens. Cuando arranca la VM de una máquina, la app construye un plan de tokens por máquina que empareja cada credencial real con su valor falso derivado. Los valores falsos 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 la tabla de sustitución en memoria del proxy, cada uno vinculado al host 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 de servicios — tokens de git, claves de nube, registros, bases de datos, claves SSH — se configuran por máquina. Abre los ajustes de la máquina (Ajustes… en el menú de la máquina, o Ajustes de «máquina»… desde el menú de una sesión) y selecciona Credenciales en Seguridad, en la barra lateral.

El panel Credenciales del editor del espacio de trabajo Web app: los campos de nombre y correo de la Identidad de Git, el estado vacío «Aún no hay credenciales» y los botones Agregar credencial e Importar archivo env…

El panel se abre con Identidad de Git (un nombre y un correo que se escriben en ~/.gitconfig dentro de la VM; déjalos en blanco para mantener los valores por defecto de git — los textos de ejemplo son solo eso, no credenciales), seguida de una lista solo de las credenciales que has configurado, agrupadas bajo encabezados de categoría (Agents, Git, Cloud, Databases, SSH, Other). Si no hay nada configurado, el panel dice Aún no hay credenciales. Abajo hay dos botones: Agregar credencial abre un selector de tipos de credencial — Git token, SSH key, AWS credentials, DigitalOcean token, Linear API key, Twilio API key, Kubernetes, Container registry, Database y Other API key — e Importar archivo env… importa en bloque desde un .env o ~/.bashrc. Pulsa Guardar; el siguiente inicio de sesión escribe los valores falsos en la VM y carga los reales en el proxy.

Las claves de API de los agentes (Anthropic, OpenAI, xAI, Moonshot y los demás proveedores de modelos) no están en este selector: se configuran en Preferencias › Modelos, que se describe a continuación. El grupo Agents solo aparece en un espacio de trabajo que todavía guarda una clave de agente propia de una versión anterior; su elemento de menú Editar en Modelos… abre Preferencias › Modelos. Para cambiar el acceso a los modelos, usa Preferencias › Modelos o el panel Modelos de la máquina.

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í. Consulta Ajustes → Credenciales para la referencia campo por campo.

Siete proveedores se gestionan automáticamente — Anthropic, OpenAI, GitHub, GitLab, DigitalOcean, Twilio y Kubernetes no necesitan reglas de token manuales; sus secciones propias 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 entiende KEY=VALUE y export KEY=VALUE, quita las comillas y los comentarios del final de línea, y omite deliberadamente todo lo que necesitaría evaluación del shell (interpolación $VAR o sustitución $(…)), así que es seguro apuntarlo a un .bashrc real. Después, una hoja de revisión muestra las variables con los valores ocultos: los nombres reconocidos (GH_TOKEN/GITHUB_TOKEN, GITLAB_TOKEN, AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN, DIGITALOCEAN_ACCESS_TOKEN, LINEAR_API_KEY, TWILIO_ACCOUNT_SID/TWILIO_AUTH_TOKEN, y las claves de proveedores de modelos ANTHROPIC_API_KEY, OPENAI_API_KEY, XAI_API_KEY, MOONSHOT_API_KEY y KIMI_API_KEY, que van al proveedor correspondiente en Preferencias › Modelos — o, en una máquina remota, a su propia sustitución Modelos) se asignan automáticamente a su tipo de credencial, mientras que los nombres no reconocidos pueden importarse como tokens manuales genéricos con un ámbito de hosts, separados por comas, que tú indicas. Las entradas ya configuradas se marcan y quedan sin seleccionar, para que una nueva importación nunca sobrescriba un secreto sin avisar.

Claves y suscripciones de los agentes

Cada agente de programación — Claude Code, Codex, Grok, Kimi y omp — obtiene su acceso a modelos de un proveedor configurado en Preferencias › Modelos (⌘, y luego Modelos). El mismo panel existe en los ajustes de cada máquina como sustitución opcional por máquina. La referencia completa — proveedores, elección de modelo por agente, sustitución por máquina, OpenRouter, servidores personalizados y modelos en el dispositivo — está en Modelos y proveedores. Esta sección cubre lo que importa para las credenciales: cómo llega una clave o una suscripción al agente sin entrar nunca en la VM.

Ventana de Preferencias titulada «Bromure — Preferencias», página Valores predeterminados, panel Modelos: una columna Proveedores (Anthropic (Claude), OpenAI y OpenRouter con una clave de API y un punto verde; xAI (Grok), z.ai (GLM), Moonshot (Kimi), Amazon Bedrock, Servidor personalizado y En el dispositivo sin configurar) y una columna Agentes (Predeterminado con Tamaños, Claude Code, Codex, Grok, Kimi, omp)

Haz clic en un proveedor de la columna Proveedores para abrir su ventana emergente. Para cada proveedor contiene un campo Clave de API; para los cuatro proveedores que ofrecen suscripciones, también contiene los controles de inicio de sesión.

Claves de API

Pega la clave en el campo Clave de API de la ventana emergente. En Preferencias, el panel guarda a medida que escribes; en los ajustes de una máquina, la clave se guarda con Guardar. Ciclo de vida:

  • En la VM: la variable habitual del agente (ANTHROPIC_API_KEY, OPENAI_API_KEY, XAI_API_KEY, …) contiene el valor falso con la forma del proveedor (sk-ant-api03-brm-…, sk-brm-…, xai-brm-…, sk-kimi-brm-…).
  • En la red: se sustituye por la clave real solo en las solicitudes a los hosts de ese proveedor (anthropic.com, openai.com, x.ai, moonshot.ai, …).
  • En reposo: las claves, como el resto de los ajustes de modelos, se guardan cifradas en models.enc (consulta Dónde residen los secretos en el anfitrión).

Las claves configuradas en Modelos no aparecen en los paneles Credenciales ni Salvaguardas, así que no tienen fila de Preguntar antes de usar. (Una clave de agente que todavía está guardada en el propio espacio de trabajo desde una versión anterior sí aparece ahí y puede requerir aprobación. Importar un archivo env ya no crea claves así: pone las claves de agentes en los ajustes de modelos.)

Desde la CLI, bromure-cli workspaces create --auth token|subscription|bedrock|local y bromure-cli vm run --auth token|subscription|bedrock|local siguen eligiendo el modo de autenticación del agente principal del espacio de trabajo.

Suscripciones: Claude, ChatGPT, Grok y Kimi

Si tienes una suscripción en lugar de una clave de API, inicia sesión. Solo hay suscripciones para Anthropic (Claude), OpenAI (ChatGPT, usado por Codex), xAI (Grok) y Moonshot (Kimi); z.ai, Amazon Bedrock, OpenRouter y los servidores personalizados solo aceptan claves, y omp funciona solo con clave de API. Una suscripción solo alimenta a su propio agente: un inicio de sesión de Claude ejecuta Claude Code, uno de ChatGPT ejecuta Codex, y así sucesivamente.

Inicies sesión como inicies sesión, el resultado es el mismo: los tokens OAuth reales solo viven en el anfitrión, y el invitado funciona con una clave ficticia — un ANTHROPIC_API_KEY falso para Claude, un ~/.codex/auth.json precargado con un JWT ficticio con caducidad muy lejana para Codex (para que el cliente nunca intente renovarlo), y tokens sustitutos en los archivos de credenciales propios de Grok y Kimi. El proxy reconoce el valor ficticio e inyecta en la red un token de acceso Authorization: Bearer válido.

Iniciar sesión desde Preferencias › Modelos

La ventana emergente del proveedor muestra uno de tres estados:

EstadoQué muestra la ventana emergente
Sin sesión iniciadaSign in with proveedor, «Inicio de sesión interactivo en una VM temporal: no se necesita clave de API.», y luego «o pega una clave de API» encima del campo Clave de API.
Sesión iniciadaUna línea verde «Sesión iniciada» con la fecha del inicio de sesión, Volver a iniciar sesión… y Cerrar sesión….
CaducadoUn panel naranja Inicio de sesión caducado — «proveedor rechazó el inicio de sesión guardado (de …). Las sesiones no pueden usarlo hasta que vuelvas a iniciar sesión.» — con Volver a iniciar sesión y Cerrar sesión….

Sign in with proveedor ejecuta el flujo de registro:

  1. Una explicación titulada Registrarse con proveedor indica lo que va a pasar. Pulsa Continuar. (El registro se rechaza si el proxy de Bromure no está en marcha.)
  2. Arranca una VM de registro desechable — temporal, aislada, sin carpetas de espacio de trabajo, sin secretos guardados y sin tabla de sustitución de credenciales. Dentro, se ejecuta el comando de inicio de sesión del propio agente.
  3. El navegador predeterminado de tu Mac abre la página de inicio de sesión del proveedor. Inicia sesión como siempre.
  4. Los tokens resultantes se capturan en el anfitrión, se cifran y se guardan; la VM desechable se apaga y se elimina.

Un inicio de sesión hecho desde Preferencias siempre lo comparten todas las máquinas. Cerrar sesión… pregunta «¿Cerrar sesión en proveedor?» — «Los espacios de trabajo que usan este inicio de sesión dejarán de funcionar hasta que vuelvas a iniciar sesión.» — y elimina el inicio de sesión guardado. Cerrar sesión… se oculta donde no puede actuar.

Iniciar sesión desde el panel Modelos de una máquina: ámbito de uso compartido

La misma ventana emergente aparece en el panel Modelos propio de una máquina. Un inicio de sesión hecho ahí termina con una pregunta, ¿Compartir con todos los espacios de trabajo?:

BotónEfecto
Todos los espacios de trabajoGuarda el inicio de sesión como el compartido y elimina el inicio de sesión propio de cada máquina para ese proveedor, para que todas las máquinas usen de verdad el nuevo.
Solo este espacio de trabajoGuarda el inicio de sesión solo para esta máquina.

El ámbito importa porque una máquina lee primero su propio inicio de sesión y solo recurre al compartido cuando no tiene uno. Una máquina que alguna vez inició sesión por su cuenta sigue usando ese inicio de sesión, incluso después de uno compartido más reciente, hasta que eliges Todos los espacios de trabajo o cierras la sesión de esa máquina. A un cliente remoto que inicia el inicio de sesión se le hace la misma pregunta; si nadie responde, el inicio de sesión se queda solo en esa máquina.

Iniciar sesión desde el chat

No tienes que pasar antes por Preferencias. Cuando un agente de una sesión necesita iniciar sesión, el chat muestra una tarjeta titulada Iniciar sesión en proveedor — «Bromure inicia sesión por ti en este Mac y mantiene tu cuenta de proveedor fuera de la máquina — el agente solo ve una clave sustituta.» — con un botón Iniciar sesión en proveedor…, y la fila de la sesión en la barra lateral dice Hace falta iniciar sesión. Cuando el inicio de sesión guardado de un agente ha sido rechazado, la tarjeta de error roja ofrece el mismo botón.

Al pulsarlo se inicia sesión sin VM desechable:

  1. El propio terminal de la sesión ejecuta el comando de inicio de sesión del agente, y la página de inicio de sesión del proveedor se abre en el navegador de tu Mac («Abriendo tu navegador para iniciar sesión…»).
  2. Cuando el agente intercambia su código de autorización por tokens, el propio proxy responde a ese intercambio: los tokens reales van directamente al almacén del anfitrión. A Claude Code y a Codex se les indica que la credencial se queda en el Mac; Grok y Kimi reciben tokens sustitutos, que sus CLI escriben en sus archivos de credenciales.
  3. El agente se reinicia con el sustituto («Sesión iniciada. Iniciando … de nuevo…»).

Un inicio de sesión desde el chat sustituye al que estaba leyendo la máquina: el de la propia máquina, si lo tiene, y si no, el compartido. Si ningún inicio de sesión llega al proxy en 5 minutos, la tarjeta indica «Bromure no recibió un inicio de sesión de proveedor a tiempo. Puede volver a intentarlo.» Solo puede haber un inicio de sesión en curso por máquina a la vez.

omp no tiene ninguna cuenta en la que iniciar sesión; su tarjeta dice «omp necesita un proveedor de modelos» y ofrece Ajustes de la máquina… en su lugar.

Advertencia: No ejecutes /login (ni el comando de inicio de sesión del agente) a mano dentro de la VM para arreglar un inicio de sesión caducado. Usa la tarjeta o Preferencias › Modelos, para que los tokens los capture el anfitrión en lugar de quedarse en la VM.

Kimi inicia sesión en la región internacional

La CLI de Kimi Code usa de forma predeterminada la región de China continental, que rechaza cuentas de otros lugares. Bromure inicia la sesión de Kimi en la región internacional (auth.kimi.ai, API en api.kimi.ai) fijando las variables de región de la CLI en la VM de registro y en cada sesión. Un inicio de sesión de Kimi capturado en la antigua región auth.kimi.com se sigue reconociendo.

Custodia de los tokens: una autorización, un renovador

La renovación de los tokens se hace íntegramente en el anfitrión, y cada inicio de sesión lo renueva un único propietario:

  • Una autorización por posición. El inicio de sesión compartido y el inicio de sesión propio de cada máquina son posiciones distintas. Para cada posición se ejecuta una renovación a la vez, y todas las máquinas que leen esa posición usan su resultado. El invitado nunca tiene un token de renovación.
  • Momento de la renovación. El anfitrión renueva unos 5 minutos antes de la caducidad, contra el endpoint de tokens del proveedor (platform.claude.com para Claude, auth.openai.com para Codex, auth.x.ai para Grok, auth.kimi.ai para Kimi). Un inicio de sesión recién registrado se guarda como ya caducado, para que el primer uso demuestre que la ruta de renovación funciona.
  • Los clones de automatización comparten la autorización. Una máquina clonada para una automatización apunta al inicio de sesión de su máquina base en lugar de copiarlo.
  • Los inicios de sesión de las CLI de tu Mac no se importan. Compartir una autorización con una CLI del anfitrión cerraría la sesión de una de las dos cada vez que la otra renovara.
  • Cuando no hay ningún token disponible para una solicitud de Claude, el proxy responde él mismo al agente en lugar de reenviar la clave ficticia: un fallo temporal vuelve como un 529 que se puede reintentar, y un inicio de sesión rechazado como un 401 que te indica que vuelvas a iniciar sesión desde Bromure. La ventana emergente muestra entonces Inicio de sesión caducado.

Credenciales de servicios

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 dirigidas a AWS en cualquier partición, por su nombre IPv4 o de doble pila (*.amazonaws.com, *.api.aws, *.amazonaws.com.cn, *.api.amazonwebservices.com.cn, los dominios de la European Sovereign Cloud y de las particiones ISO; incluidos GovCloud, los hosts regionales, FIPS y los hosts S3 de estilo bucket), quita la firma del invitado, inyecta el X-Amz-Security-Token real cuando hay un token de sesión, y vuelve a firmar con el secreto real antes de que la solicitud salga de tu Mac. La salvaguarda de AWS cubre los mismos hosts, y la reescritura de las credenciales que crea la VM (más abajo) también los cubre, además de public.ecr.aws. Cada refirma correcta emite un evento de auditoría credential.aws_sign con una clave de acceso oculta, que aparece como fila Credencial usada en la Cronología de seguridad.

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).

Credenciales que crea la VM

Algunas llamadas emiten una credencial nueva: aws sts assume-role / get-session-token / get-federation-token, aws iam create-access-key, las credenciales de rol de IAM Identity Center, GetCredentialsForIdentity de Cognito, aws ecr get-login-password y, en DigitalOcean, doctl registry login, doctl kubernetes cluster kubeconfig save (y su llamada de credenciales) y doctl spaces keys create. El proxy retiene la respuesta a una llamada así y reemplaza cada secreto que contiene por un señuelo antes de que la VM la vea. Una clave temporal de AWS conserva su ID de clave de acceso real, con un secreto y un token de sesión señuelo, para que el refirmador sepa con qué clave firmó el invitado. Un token de registro o de clúster se convierte en un señuelo que solo se cambia de nuevo por el valor real en ese registro o clúster.

Los valores reales se guardan, cifrados, en la configuración del espacio de trabajo, de modo que los señuelos que la VM almacenó (en ~/.aws, ~/.docker/config.json o un kubeconfig) siguen funcionando tras un reinicio. Una clave de AWS emitida se vuelve a firmar con su propio secreto y token de sesión. Una vez caducada, las solicitudes firmadas con ella se rechazan en lugar de refirmarse con la clave propia del espacio de trabajo, lo que las ejecutaría con otra identidad. Las credenciales caducadas se descartan 30 días después de caducar.

Una respuesta que el proxy no puede reescribir por completo nunca se transmite: el invitado recibe un 502 en su lugar. Las llamadas que fijan un secreto elegido por la propia VM, que ningún señuelo puede sustituir, se rechazan en cualquier modo de las salvaguardas: iam:CreateLoginProfile, UpdateLoginProfile, CreateServiceSpecificCredential y ResetServiceSpecificCredential. Una solicitud de consentimiento de AWS nombra la llamada que firmaría (por ejemplo sts:AssumeRole), y cada credencial emitida genera un evento credential.minted.

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

Amazon Bedrock es un proveedor de modelos para todos los agentes, no un modo de autenticación de uno solo. Activa Usar Amazon Bedrock en la ventana emergente Amazon Bedrock de Preferencias › Modelos (o del panel Modelos de una máquina) y elige los ID de modelo de Bedrock por agente. Claude Code funciona de forma nativa con Bedrock; los demás agentes llegan a él a través de la API compatible con OpenAI de Bedrock. Las solicitudes se firman con las credenciales de AWS propias de cada máquina (Credenciales → AWS, estáticas o SSO) por la misma ruta de refirma, ya que los endpoints de Bedrock son hosts *.amazonaws.com — o, si pegas una en el campo Clave de API de Bedrock (opcional; si no, firman las credenciales de AWS) de la ventana emergente, con esa clave, que la VM solo ve como un valor falso bedrock-brm-…. La ventana emergente también acepta una Región de AWS; déjala vacía para usar la región de AWS de cada máquina. Consulta Modelos y proveedores.

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 1Password —op://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 archivo env… en el panel Credenciales) reconoce automáticamente los valores op:// — con nombres reconocidos como ANTHROPIC_API_KEY o arbitrarios como STRIPE_KEY — y guarda 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 la configuración de la API de Linear en tu navegador; las claves se obtienen en linear.app → Settings → API). El valor falso (lin_api_ + 40) se exporta como LINEAR_API_KEY, que el SDK de Linear, los servidores MCP y las herramientas de CLI leen automáticamente; la sustitución 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 de los disparadores de automatización por incidencias de Linear — consulta Automatizaciones.

Twilio

Añade una credencial Twilio API key con el SID en Account SID (AC…) or API Key SID (SK…) y el secreto en Auth Token / API Key secret (ambos de console.twilio.com). Twilio se autentica con HTTP Basic, donde el SID es una identidad — viaja en la URL de la solicitud — y solo el token es secreto. Ciclo de vida:

  • En la VM: TWILIO_ACCOUNT_SID contiene el SID real y TWILIO_AUTH_TOKEN un valor falso brm-twilio-…, para que los SDK de Twilio y la CLI los lean sin configuración.
  • En la red: en las solicitudes a twilio.com, el proxy sustituye por los reales tanto el token falso sin más como el bloque de autenticación Basic SID:token ya codificado en base64.
  • Aprobación: mediante Preguntar antes de usar en el panel Salvaguardas.

Importar archivo env… reconoce TWILIO_ACCOUNT_SID / TWILIO_API_KEY_SID y TWILIO_AUTH_TOKEN / TWILIO_API_SECRET y los junta en una sola credencial de Twilio.

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—.
  • Claves de un agente del host. Una clave cuya mitad privada no puede salir de su dispositivo —una YubiKey u otra llave de seguridad detrás de gpg-agent, Secretive, 1Password— se añade en su lugar con Desde el agente del host…. Elige el socket del agente (vacío = el propio SSH_AUTH_SOCK de la app, que para una app abierta desde el Finder es el agente de macOS, no uno que exporte tu shell; para gpg-agent usa ~/.gnupg/S.gpg-agent.ssh), haz clic en Cargar y marca las claves que el espacio de trabajo puede usar. No se copia nada: la VM solo ve las claves marcadas —y solo mientras el agente las tiene, así que una llave desenchufada no se ofrece— y sus peticiones de firma se reenvían a ese agente, de modo que la solicitud de toque o PIN aparece en tu Mac como siempre (la petición la espera hasta dos minutos). Las demás claves del agente siguen siendo invisibles para la VM, y una petición de firmar con una de ellas se rechaza.

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, importada o de un agente del host.

Nota: Tu ssh-agent de inicio de sesión de macOS (el de launchd) —o cualquier otro agente del host— deliberadamente nunca se expone a la VM en su conjunto. Solo las claves por espacio de trabajo, las claves que importaste explícitamente y las claves concretas de agentes del host que elegiste 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 apague la VM de la máquina.
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 autorizaciones y denegaciones solo se guardan en memoria y se revocan al apagarse la VM. «El resto de la sesión» nunca sobrevive a un reinicio de la VM, y nada se conserva entre ejecuciones de la app.
  • Sesiones headless. En una sesión SSH o headless, la solicitud aparece en el tmux de la máquina en lugar de como 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 solo están en memoria, la ventana queda vacía cuando caducan las autorizaciones, cuando se apaga la VM (autorizaciones de ámbito de sesión) y cuando se cierra la app. Es un panel de control del presente, no un registro de auditoría: para el historial, usa la Cronología de seguridad y el 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. Si la máquina se estaba ejecutando en segundo plano, primero se trae a la pantalla, y su imagen congelada se tiñe de rojo.
  3. Aparece una alerta crítica titulada Este entorno puede haberse visto comprometido: «Bromure detectó un intento saliente de filtrar una credencial de sesión desde “máquina” a un host para el que no se emitió. La VM se ha pausado.» En Filtraciones detectadas: enumera una línea por filtración: una vista previa del token (como sk-a…f9q3), el nombre de la credencial, el host para el que se emitió y el host al que se envió.
  4. La detección se registra como una fila roja de Intermediación de credenciales en la Cronología de seguridad y, en las instalaciones inscritas, como un evento credential.exfiltration.

La alerta ofrece cuatro botones:

BotónEfecto
Apagar (predeterminado)Detiene la VM y marca la máquina como comprometida.
BloquearDetiene solo esta solicitud (que ya recibió un 451) y reanuda la VM. No se recuerda nada: si el agente lo vuelve a intentar, el detector salta de nuevo y la alerta se reabre.
PermitirConfía en el host observado solo durante el resto de esta sesión y reanuda la VM. A partir de entonces, la credencial se sustituye y se envía a ese host (y a sus subdominios), y las solicitudes hacia él dejan de marcarse. La decisión se registra como una fila verde de Intermediación de credenciales, «allowed by user for this session», y, en las instalaciones inscritas, como credential.exfiltration_allowed. La lista de permitidos se vacía al apagarse la VM.
Guardar para investigaciónPide una carpeta, exporta disk.img (una copia del disco de sistema de la VM), home.tar.gz (el directorio personal de la máquina) y shares/<nombre>.tar.gz por cada carpeta compartida, y luego apaga la VM y marca la máquina como comprometida. El estado de la RAM de la VM se descarta.

Solo Apagar responde a la tecla Retorno; Bloquear, Permitir y Guardar para investigación no tienen equivalente de teclado, así que reanudar una VM posiblemente hostil — y más aún enviarle la credencial — siempre requiere un clic explícito. Solo se muestra una alerta a la vez; las detecciones repetidas mientras está abierta se descartan (cada una sigue bloqueada).

Consejo: Permitir existe para configuraciones legítimas entre hosts — por ejemplo, una clave con formato de OpenAI que una herramienta envía deliberadamente al endpoint compatible con OpenAI de otro proveedor. Si no reconoces el destino, no lo permitas.

Si la máquina se está replicando desde un cliente remoto, la pregunta aparece en el cliente como una solicitud pendiente con Apagar, Bloquear y Permitir (guardar para investigación necesita un selector de carpetas local, así que solo se ofrece en el propio Mac). Solo la VM afectada queda en pausa; el anfitrión sigue atendiendo a todas las demás máquinas. Una solicitud sin respuesta apaga la VM a los 3 minutos.

Una máquina marcada como comprometida se niega a arrancar hasta que lo remedies. Al iniciarla aparece «To continue, the VM disk image and the persistent home folder must be wiped. Your tokens, ssh keys, and workspace settings are preserved.» con Borrar e iniciar y Cancelar (Retorno no confirma el borrado). Presta atención a la advertencia que lo acompaña: las carpetas compartidas NO se borran, así que si el compromiso llegó a través de un paquete o un archivo de una carpeta compartida, puede que siga ahí; revisa esas carpetas antes de retomar 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.

El detector en sí está siempre activo. Lo que puedes desactivar, por máquina, es la interrupción — consulta la sección siguiente.

Vías de escape

Algunos hosts y clientes no funcionan con una interceptación completa: un servidor con CA privada en el que el anfitrión no confía, un cliente que fija el certificado de su servidor, o una configuración legítima que dispara una y otra vez la alerta de compromiso. Tres ajustes por máquina, al final del panel Salvaguardas, relajan el límite en esos casos sin desactivarlo. Los tres se aplican al momento, sin reiniciar.

AjustePredeterminadoQué hace
Permitir omisión insegura por solicitud (X-bromure-insecure)ActivadoCuando una solicitud a un host autofirmado o con CA privada falla la validación del certificado, el agente puede reintentarla con la cabecera X-bromure-insecure: yes para omitir la validación del certificado de ese servidor. La interceptación, el trazado y la protección contra filtraciones siguen activos, y Bromure no inyecta ninguna credencial real en esa solicitud: solo salen los valores falsos del invitado. Cada uso queda registrado en la Cronología de seguridad como una fila de TLS ascendente: «allowed — certificate validation skipped (X-bromure-insecure); no credentials injected». Activado de forma predeterminada porque solo actúa cuando el invitado envía la cabecera; desactívalo para prohibir la cabecera por completo.
Desactivar la interceptación transparenteDesactivadoDetiene el desvío a nivel de red que obliga al HTTP/HTTPS de la VM a pasar por Bromure. Los sockets en bruto y los clientes con certificado fijado llegan entonces directamente a la red real y al certificado real del servidor. El proxy en sí se mantiene: HTTP(S)_PROXY sigue definido, así que las herramientas que respetan el proxy (apt, git, pip, curl, node…) y las llamadas de API del propio agente siguen pasando por Bromure y conservan la sustitución de credenciales, el trazado y las salvaguardas. El tráfico que ignora los ajustes de proxy deja de estar cubierto por las reglas de salida.
No alertar sobre la exfiltración de credencialesDesactivadoSuprime la alerta de compromiso y la pausa de la VM. La solicitud que filtra se sigue bloqueando con un 451 y se sigue registrando en la Cronología de seguridad («blocked — exfiltration attempt (alerts off, VM not paused)»); solo desaparece la interrupción.

Advertencia: Cada uno de estos ajustes cambia algo de protección por compatibilidad. Prefiere el más acotado: la cabecera por solicitud para un certificado no confiable, Permitir en la alerta de compromiso para un destino de confianza, y los interruptores de toda la máquina solo para una máquina que no puede funcionar de otro modo.

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.enc, kimi-subscription.encAlmacenes de suscripciones cifrados con AES-GCM: el inicio de sesión compartido más el inicio de sesión propio de cada máquina, 0600.
models.encLos ajustes globales de modelos de Preferencias › Modelos, incluidas las claves de API de los proveedores, cifrados con la clave del almacén.
pii/<workspace-id>.keyLa clave propia de cada máquina detrás de los sustitutos de la protección de datos personales (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, que se copia en las máquinas nuevas.
profiles/<id>/ssh/Las claves SSH emitidas por máquina (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 se producen las sustituciones. Abre la Cronología de seguridad y filtra por Intermediación de credenciales: cada sustitución aparece como una fila del tipo sk-a…f9q3 → api.anthropic.com — swapped in …. Con el trazado activado para la máquina, también puedes ejecutar:

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 canal de tokens de Claude que usa la VM de registro — un puerto que comparte con el puente de inferencia local (se configuran en flujos distintos; consulta Modelos y proveedores).
8447El canal de tokens de Codex que usa la VM de registro (tokens de acceso, de renovación y de ID).

Los dos canales de tokens son unidireccionales: el anfitrión solo puede escribir valores falsos en la VM, y la VM solo puede enviar valores reales al anfitrión. No existe ninguna solicitud con la que la VM pueda pedir de vuelta un token real.

Comandos de CLI relacionados (referencia completa en CLI, API y MCP):

ComandoPropósito
bromure-cli workspaces create --auth token|subscription|bedrock|localCrea un espacio de trabajo con el modo de autenticación de su agente principal.
bromure-cli vm run --auth token|subscription|bedrock|localArranca una VM y elige el modo de autenticación de un espacio de trabajo creado 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.