← Volver a todas las publicaciones
Publicado el · por Renaud Deraison

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.

Dónde vive la clave realClaves guardadas en una consola alojadaTu portátilUn compañeroOtros usuariosclaves realesAlmacén de espacios del proveedorsk-ant-… sk-proj-… AIza…las claves de cada usuario vinculadoSistema heredado, en retiradaEl intruso ejecuta inferencia masivaLa factura va al titular de la clave hasta que se revoca.Claves en Bromure Agentic CodingTu Mac · models.encAES-GCM, clave maestra en el Data Protection KeychainVM Linux · entorno y config del agenteANTHROPIC_API_KEY=sk-ant-api03-brm-… (sustituto)El proxy del Mac comprueba el destino de cada peticiónapi.anthropic.comsustituto → clave realcualquier otro host451, VM en pausaNinguna copia alojada. La VM solo tiene sustitutos.
Izquierda: las claves guardadas en una consola alojada comparten servidor con las de todos los demás usuarios, y una sola intrusión las alcanza todas. Derecha: en Bromure, la clave real existe en un archivo cifrado en tu Mac y en la petición que el Mac envía al proveedor. Todo lo que guarda la VM es un sustituto, y un sustituto enviado a cualquier otro sitio detiene la máquina.

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.