Las claves estaban en su consola
La noche del 16 de octubre, alguien entró en un sistema heredado de OpenCode y alcanzó las claves de API de OpenAI, Anthropic y Google que cerca del 1,4 % de los usuarios de OpenCode Console habían guardado en sus espacios de trabajo. OpenCode lo calificó de ataque de destilación a gran escala, y usuarios informaron de facturas de proveedores que no habían generado. En Bromure Agentic Coding, las claves de los proveedores se quedan cifradas en tu Mac, el enrutamiento entre varios proveedores se ejecuta en tu Mac, y cualquier copia de una clave que sale de la VM es un sustituto que ningún proveedor acepta.
Tu portátil estaba bien. Tu clave de Anthropic se robó de un servidor en el que la pegaste hace meses.
El sábado 17 de octubre, OpenCode avisó a parte de sus usuarios de que había “identified unauthorized access to a legacy system”, un sistema que estaba en pleno proceso de retirada. La intrusión ocurrió durante la noche del 16 al 17 de octubre. Su aviso decía que “third party provider keys (eg OpenAI, Anthropic) saved in your workspace may have been exposed”. OpenCode cifró la proporción de usuarios de OpenCode Console afectados en torno al 1,4 %, limitada a cuentas con proveedores externos vinculados, y escribió a cada una de ellas. Describió el incidente como “related to a large scale distillation attack” y dijo que estaba trabajando con Anthropic, OpenAI y Google. OfficeChai, Startup Fortune y otros lo cubrieron ese mismo día.
OpenCode dijo que no podía confirmar si las claves se habían usado y que el incidente seguía en curso. Usuarios en X informaron de cargos en claves que solo habían usado con OpenCode, algunos de cientos de dólares. El consejo que todos publicaron fue el mismo: revocar cada clave guardada en la Console desde el panel de cada proveedor, emitir claves nuevas y actualizar cada lugar donde estaba la antigua.
Las víctimas no habían ejecutado un paquete malicioso ni abierto un repositorio envenenado. Un intruso se llevó sus claves de un servidor en el que ellas mismas las habían pegado.
Por qué las claves estaban ahí
OpenCode es un agente de programación de código abierto que habla con más de 75 proveedores de modelos. La Console es su parte alojada, donde puedes guardar tus propias claves de proveedores en un espacio de trabajo y dejar que el servicio las use por ti. El resumen de ai-tldr las describe como claves guardadas “for bring-your-own-key use”. Es una comodidad: una cuenta, todos los proveedores, sin ir pasando claves de un portátil a otro.
También convierte la base de datos de un proveedor en un llavero. Cada usuario que vinculaba un proveedor añadía otra credencial activa y facturable al mismo almacén. Meses después, un sistema que el proveedor estaba retirando seguía teniendo acceso a ese almacén.
Una clave de API de un modelo es capacidad de gasto. Quien la tiene puede comprar inferencia a tu cuenta hasta que la revoques, al ritmo que el proveedor permita. El motivo del que se informó, la “destilación”, consiste en recolectar en volumen las respuestas de un modelo potente para entrenar uno más barato. Eso requiere muchísimas peticiones, y una clave robada hace que las pague otro.
Una copia, en tu Mac
Bromure Agentic Coding ejecuta Claude Code, Codex, Grok, Kimi y omp en VM Linux en tu Mac. Registras cada proveedor de modelos una sola vez, en Preferences › Models: pega una clave de API o haz clic en Sign in with proveedor para usar una suscripción de Claude, ChatGPT, Grok o Kimi sin ninguna clave de API.
Las claves van a models.enc, en la carpeta de soporte de la app, cifradas
con AES-GCM bajo una clave maestra propia de cada instalación. Esa clave
maestra vive en el Data Protection Keychain de macOS, ligada a la identidad
de firma de la app, con la sincronización de iCloud desactivada. Nunca sale
del Mac. Bromure no tiene una cuenta donde vivan tus claves ni un espacio
de trabajo alojado con el que se sincronicen.
Bromure te da la comodidad de la consola en el propio Mac. Todas las máquinas leen el mismo panel, y una máquina puede sustituirlo con sus propias claves. Codex, Grok, Kimi y omp pueden llegar a Bedrock, OpenRouter, xAI y Moonshot a través de un proxy de traducción que se ejecuta en el Mac y guarda allí la clave real. Claude Code llega a OpenRouter y z.ai directamente con un sustituto.
En la VM, todo es un sustituto
El agente sigue necesitando ANTHROPIC_API_KEY u OPENAI_API_KEY para
arrancar, y recibe una. Dentro de la VM esas variables contienen sustitutos
con la forma de las claves reales: sk-ant-api03-brm-… para Anthropic,
sk-brm-… para OpenAI, xai-brm-… para xAI, sk-kimi-brm-… para Kimi. El
HTTPS del agente pasa por un proxy en el Mac, que cambia el sustituto por
la clave real solo en las peticiones a los hosts propios de ese proveedor:
anthropic.com, openai.com, x.ai, moonshot.ai. La coincidencia es
exacta o por subdominio, nunca por subcadena, así que
api.openai.com.evil.example no obtiene nada.
Con una suscripción es igual, pero sin clave. El inicio de sesión se hace en una VM desechable o mediante el propio login del agente, el proxy captura los tokens OAuth en el Mac y el agente se queda con un sustituto. El host renueva el token de acceso unos cinco minutos antes de que caduque. La VM nunca guarda un refresh token.
Hoy muchas herramientas ofrecen sincronizar su configuración con la nube
del fabricante: una CLI que hace “copia de seguridad” de su config, un
editor que guarda tu espacio de trabajo en tu cuenta, un plugin con panel.
Dentro de una máquina Bromure, la config que suben esas herramientas
contiene sk-ant-api03-brm-…. Un sustituto guardado en el servidor de otro
no vale nada allí. Ningún proveedor lo acepta, y solo se convierte en una
clave real cuando la petición pasa por tu Mac hacia el proveedor para el
que se creó.
El proxy también detecta la subida en sí. Examina cada petición saliente, cabeceras y cuerpo, en busca de sustitutos que vayan a un destino distinto de su propio proveedor. Una sincronización de config que lleva un sustituto de Anthropic a un servidor de terceros recibe un HTTP 451. No se reenvía nada, la VM se pausa y el Mac muestra This environment may have been compromised, indicando la vista previa del token, la credencial, el host al que pertenece y el host al que se envió. Te enteras el día en que una herramienta intenta copiar tu clave fuera de la máquina, meses antes del aviso de brecha de cualquier proveedor.
La mañana siguiente, en Bromure
Supón que aun así te llegó ese correo, porque también usaste una clave en otro sitio. Todas las guías dicen las mismas tres cosas: revocar, reemplazar en todas partes y revisar el uso. En Bromure, cada paso es breve.
Reemplazar en todas partes. La clave real vive en un solo lugar. Pega
la nueva en el popover del proveedor, en Preferences › Models, y
Bromure actualiza cada máquina en marcha alrededor de un segundo y medio
después de que dejes de escribir: el mapa de sustitución, el entorno de los
agentes y sus archivos de config. Los agentes cuya credencial cambió se
reinician en su pestaña con sus flags de reanudación, así que la
conversación continúa, y la VM nunca se reinicia. No hay archivos .env,
secretos de CI ni portátiles de compañeros que perseguir por las copias
dentro de las VM, porque esas copias eran sustitutos.
Revisar el uso. En el nivel AI request details, con el que arrancan
las máquinas nuevas, el Mac registra cada intercambio con un proveedor de
modelos como un registro llm.request: proveedor, host, modelo, estado y
recuento de tokens de entrada, salida y caché. Cuando el panel de un
proveedor muestra un pico a las 3 de la madrugada, puedes cotejarlo con lo
que enviaron tus máquinas. bromure-cli trace summary y bromure-cli trace hostnames dan la vista por máquina en un terminal. Cada sustitución
de una clave de proveedor aparece en la Security Timeline como una fila
Credential brokering, con una vista previa enmascarada y el host, en
una tabla con una columna Workspace. Todo lo que figure en la factura
del proveedor y que tus máquinas no enviaron vino de otra persona.
Para un equipo, Bromure Enterprise Manager agrega esos mismos
recuentos de llm.request por usuario, por espacio de trabajo y por
modelo, sin subir prompts, respuestas ni secretos. Una clave robada aparece
como un gasto que no coincide con ninguna instalación.
O prescinde de la clave. Para Claude Code, Codex, Grok y Kimi, un inicio de sesión con suscripción reemplaza la clave de pago por uso, y los tokens que genera se quedan en el Mac y se renuevan allí. Así no queda ninguna clave de API de larga duración que un tercero pueda guardar.
Una copia cifrada, en tu Mac
Las claves de proveedores y los inicios de sesión están en models.enc, bajo una clave maestra en el Data Protection Keychain. Bromure no tiene ningún espacio de trabajo alojado ni cuenta que los guarde.
Enrutamiento entre proveedores, en local
Todas las máquinas leen un único panel Models. Los agentes llegan a otros proveedores a través de un proxy en el Mac que guarda la clave real.
Sustitutos dondequiera que acabe una copia
La VM, sus archivos de config y todo lo que una herramienta sincroniza con la nube contienen sustitutos. Un sustituto enviado al host equivocado recibe un 451 y pausa la máquina.
Rota una vez, audita cada petición
Una clave nueva llega a cada máquina en marcha sin reiniciar. Cada intercambio con un modelo queda registrado con su modelo y sus recuentos de tokens.
Dónde debería vivir una clave
Cada lugar donde pegas una clave de proveedor es un lugar más desde el que pueden robarla. Los portátiles pillan stealers, los repositorios se rastrean y, como ha demostrado esta semana, los proveedores retiran sistemas que todavía alcanzan las claves de sus clientes.
Guarda la clave real en un único archivo cifrado en tu Mac y pon sustitutos en todos los demás sitios. Para la versión del mismo problema del lado del portátil, lee El stealer se llevó los sustitutos y El agente filtró su propia clave.