Cuando tu agente de programación publica tus secretos: guía de análisis forense de IA, contención y auditoría

Tiempo de lectura: 20 minutos

TL;DR

Hace poco me llamaron para un incidente que espero ver cada vez más: un agente de programación empaquetó ficheros a los que tenía acceso y los subió a un repositorio público de GitHub. Dentro había datos personales y tokens en vigor. Nadie atacó nada. El agente hizo algo para lo que tenía permisos, e internet se encargó del resto. Esta es la guía que le daría a cualquiera que se encuentre en la misma situación: detén el agente y conserva sus registros antes de que caduquen, rota todos los secretos antes de tocar el historial de git, asume que borrar o hacer privado el repositorio no borra los datos, limpia lo que GitHub permita limpiar, audita para qué se usaron los tokens filtrados y gestiona los datos personales con el reloj de 72 horas del RGPD en marcha. La segunda mitad es el análisis forense de IA que la mayoría de los equipos nunca ha hecho: leer los paneles y las API de uso de OpenAI y Anthropic para averiguar si alguien ha gastado tus tokens, y en qué.


Una nota sobre qué es esto. El caso que ha motivado este artículo es real y está anonimizado: ni cliente, ni producto de agente, ni detalles de los datos. Lo que sigue es una guía defensiva construida a partir de esa experiencia y de documentación pública, que cito sobre la marcha. Las consolas de los proveedores cambian; comprueba la documentación vigente antes de fiarte de una ruta de menú bajo presión.

El tipo de incidente que nadie había ensayado

Tenemos veinte años de procedimientos para el caso de un desarrollador que sube una contraseña a un repositorio. Casi ninguno para cuando el desarrollador es un programa con acceso a la shell, credenciales de git y una tarea que terminar.

La mecánica del caso fue de lo más corriente. Un agente de programación, con los accesos que se le habían dado, empaquetó un conjunto de ficheros y los subió a un repositorio público. Algunos de esos ficheros contenían datos personales. Otros contenían tokens, entre ellos claves de API de proveedores de IA. No hubo inyección de prompts ni ninguna skill maliciosa: solo un agente capaz de ejecutar git push contra un remoto público y nada que se interpusiera entre esa capacidad y el resultado.

Los datos dicen que no es un caso aislado. El informe State of Secrets Sprawl 2026 de GitGuardian contabilizó 28,65 millones de secretos nuevos incrustados en commits públicos de GitHub durante 2025, un 34 % más en un año, y los secretos de servicios de IA crecieron un 81 %, hasta superar los 1,27 millones. La cifra que más me llamó la atención: los commits hechos con ayuda de un agente de programación muy extendido mostraron una tasa de filtración de secretos del 3,2 %, frente al 1,5 % de media en todos los commits públicos. Es investigación de un fabricante y un solo dato, pero encaja con lo que veo: los agentes van más rápido que la higiene que los rodea. El mismo informe encontró más de 24.000 secretos solo en ficheros de configuración MCP. Ya he escrito sobre skills de agente convertidas en armas y sobre la trampa de las dependencias en el código generado por IA; este caso es el pariente menos vistoso de ambos, porque no necesita ningún adversario.

El reloj contra el que corres de verdad

Un hecho decide el orden de los pasos: la carrera es contra la automatización, no contra una persona que quizá tropiece con el repositorio.

Los push públicos se rastrean de forma continua. La Unit 42 de Palo Alto documentó una campaña capaz de lanzar un ataque completo en cinco minutos desde que una credencial de AWS aparecía en un repositorio público de GitHub, y una investigación posterior de Clutch Security vio claves de AWS expuestas explotadas en cuestión de minutos. Da por hecho que, para cuando una persona se dio cuenta del push, todos los secretos que contenía ya habían sido recolectados. De esa premisa sale el orden de las operaciones.

Paso 0: detén el agente y conserva las pruebas

Mata la sesión del agente. Revoca la credencial de git con la que hizo el push (la clave SSH, el token de acceso personal o la instalación de la app) para que un bucle de reintentos o una tarea programada no pueda volver a subir nada mientras trabajas.

Después conserva las pruebas, hoy, antes de que desaparezcan solas. La transcripción del agente es tu mejor registro de lo que hizo y por qué: qué ficheros leyó, qué comandos ejecutó, qué subió y adónde. Esas transcripciones no se guardan para siempre. Claude Code, por ejemplo, guarda las sesiones en JSONL bajo ~/.claude/projects/PROYECTO/ y las borra a los 30 días por defecto (el ajuste cleanupPeriodDays). Codex CLI, de OpenAI, guarda sus registros de sesión en JSONL bajo ~/.codex/sessions/. Sea cual sea el agente, localiza dónde guarda las sesiones y cópialas a un lugar seguro, junto con el historial de la shell, el repositorio local con su git reflog y los registros de CI si el push salió de un pipeline. Calcula el hash de las copias. Puede que las necesites ante un regulador, un cliente o un juez, y un informe de incidente que diga «los registros ya habían rotado» no es uno que quieras escribir.

Paso 1: averigua exactamente qué se ha filtrado

No lo reconstruyas de memoria. Clona el repositorio público en un entorno aislado y analiza todo el historial, no solo el estado actual:

git clone --mirror https://github.com/ORG/REPO.git leaked.git
gitleaks git -v --report-format json --report-path gitleaks.json leaked.git
trufflehog git file://leaked.git --results=verified,unknown

Gitleaks te da amplitud; TruffleHog puede comprobar qué credenciales siguen vivas, lo que te dice qué rotar primero. Después revisa los ficheros a mano en busca de datos personales, porque los escáneres son buenos con los tokens y malos con un CSV de nombres de clientes.

Construye una única tabla de inventario y consérvala durante todo el incidente: cada secreto (tipo, proveedor, alcance, propietario, primer commit en el que aparece) y cada fichero con datos personales (categorías de datos, número aproximado de personas, de quién son). Todo lo que viene después trabaja sobre esa tabla.

Paso 2: rota todo antes de tocar el historial

Este es el paso que los equipos hacen al revés. El instinto es borrar el fichero, forzar el push y quedarse tranquilo. La propia guía de GitHub sobre cómo eliminar datos sensibles es tajante: si el dato sensible es un secreto, «como primer paso tienes que revocar y/o rotar ese secreto». Un secreto rotado es inofensivo allí donde sobrevivan copias. Un secreto borrado del historial pero todavía válido sigue siendo una clave válida en la cosecha de otro.

Ordena la rotación por radio de impacto. Primero las claves de administración y de organización (una clave de administración de un proveedor de IA, una clave raíz o de IAM en la nube, un token de GitHub con alcance de organización), porque permiten a un atacante crear credenciales nuevas que sobreviven a tu rotación. Después las claves de servicios en producción y, por último, todo lo demás. Tras cada rotación, confirma que la credencial antigua está realmente muerta, no solo que la nueva funciona.

Dos notas específicas de IA. La primera: GitHub tiene un programa de socios de detección de secretos: cuando detecta la clave de un socio en un repositorio público, avisa al proveedor, que puede revocarla. Anthropic afirma que desactiva automáticamente las claves de la API de Claude detectadas por esta vía y envía un correo al usuario afectado. OpenAI es integrador del programa de GitHub desde 2021, pero su guía de seguridad de claves se limita a decirte que rotes de inmediato una clave filtrada. Trata la revocación por parte del proveedor como un extra, nunca como tu control. Y guarda ese correo de Anthropic: su marca de tiempo te sirve de referencia para la cronología. La segunda: rotar una clave de IA rompe todo lo que la usaba. Ten la clave nueva lista en tu gestor de secretos antes de matar la antigua, o estarás haciendo respuesta a incidentes y gestionando una caída del servicio a la vez.

Paso 3: corta la hemorragia, y entiende lo que eso no consigue

Ahora reduce la exposición: haz privado el repositorio o retíralo. Hazlo, pero teniendo claro lo que consigue y lo que no, porque aquí es donde falla el modelo mental de casi todo el mundo.

GitHub documenta que, cuando un repositorio público pasa a privado, «sus forks públicos se separan en una nueva red» y siguen siendo públicos. Si lo borras, el fork público activo más antiguo pasa a ser el nuevo repositorio de origen. Truffle Security demostró en 2024 que, mientras exista un solo fork, los commits de la red siguen accesibles por su hash, y GitHub respondió que ese comportamiento es intencionado. Forzar el push tampoco ayuda: Sharon Brizinov analizó todos los eventos de force push desde 2020 registrados en el archivo público GH Archive, recuperó los commits «borrados» por su SHA, encontró miles de secretos en vigor y cobró unos 25.000 dólares en programas de bug bounty. El evento del push, con el hash del commit, está en un archivo público que no controlas.

Así que la contención de los datos es, en el mejor de los casos, parcial. La contención de los secretos es total, si hiciste el paso 2. Por eso el paso 2 va primero.

srf_agentleak_exploitation_tree
Figura 1. Por qué «hemos borrado el repositorio» no es contención. Al atacante le basta una sola vía hasta los datos (el repositorio vivo, un fork o un clon hecho antes de retirarlo, un commit colgante recuperado por su SHA desde GH Archive o la red de forks en general) y una sola forma de usarlos. La única rama que puedes cerrar por completo es la de las credenciales: una vez rotadas, todas sus copias dejan de valer. Los datos personales no tienen equivalente a la rotación.

Antes de cambiar la visibilidad, registra lo que puedas ver. En Insights → Traffic, GitHub muestra los clones y los visitantes de los últimos 14 días (en UTC, actualizados cada hora) a cualquiera con permiso de push. Haz capturas, anota la lista de forks y quién ha marcado el repositorio con estrella. No te dirá quién, pero sí si alguien lo hizo, y eso importa mucho para la evaluación de los datos personales del paso 6.

Paso 4: limpia lo que GitHub puede limpiar

Con los secretos muertos y el repositorio en privado, reescribe el historial como es debido. GitHub recomienda git-filter-repo 2.47 o posterior con su modo de datos sensibles:

git-filter-repo --sensitive-data-removal --invert-paths --path ruta/al/fichero-filtrado
git-filter-repo --sensitive-data-removal --replace-text ../patrones.txt

Después contacta con el soporte de GitHub indicando el nombre del repositorio, el número de pull requests afectadas y los «first changed commits» que indica git-filter-repo, para que eliminen las vistas en caché, desreferencien las pull requests y pasen el recolector de basura. Para los forks, la política de retirada de información privada cubre credenciales de acceso y tokens de terceros, así como identificadores personales como los números de documentos de identidad oficiales. GitHub no deshabilita los forks automáticamente, así que incluye en la solicitud todos los que conozcas, con enlaces a los ficheros, números de línea y por qué cada elemento supone un riesgo. Otras categorías de datos personales pueden no encajar limpiamente en esa política, otro motivo más para que la evaluación RGPD del paso 6 parta de que ha habido exposición en lugar de confiar en la retirada.

Si quieres saber qué puede seguir alcanzando alguien de fuera, usa las mismas herramientas que usaría un atacante: el modo github-experimental --object-discovery de TruffleHog enumera los commits ocultos y borrados de la red de un repositorio. Es lento y está limitado por las cuotas de la API, pero responde a la pregunta con honestidad.

Paso 5: audita para qué se usaron los tokens

La rotación impide el abuso futuro. No te dice nada de lo que pasó entre el push y la rotación. Para cada secreto vivo de tu inventario, extrae los registros del proveedor de esa ventana: registros de auditoría de la nube, el registro de auditoría de GitHub, los registros de acceso a bases de datos. Para las claves de IA, eso significa los paneles y las API de uso de los proveedores, que la mayoría de los equipos nunca ha mirado con ojos de investigador. Es la parte de análisis forense de IA y ocupa la segunda mitad de este artículo.

Antes, responde a una pregunta: ¿alguna de las claves filtradas tenía permisos de administración? Una clave de administración permite al atacante crear claves nuevas, añadir usuarios o cambiar la configuración, y así acabas rotando la clave filtrada y sigues sangrando. Con esas claves, el registro de auditoría va antes que el informe de uso.

Paso 6: los datos personales y el reloj de 72 horas

Un repositorio público con datos personales es una brecha de datos personales según el RGPD: una pérdida de confidencialidad, puedas demostrar o no que alguien los descargó. El artículo 33 obliga a notificar a la autoridad de control «sin dilación indebida y, de ser posible, a más tardar 72 horas» después de haber tenido constancia de ella, salvo que sea improbable que la brecha suponga un riesgo para los derechos y libertades de las personas. El artículo 34 añade la comunicación a los afectados cuando el riesgo sea alto. Y el artículo 33.5 exige documentar la brecha, sus efectos y las medidas correctoras aunque decidas no notificar.

En España, la AEPD ofrece Asesora Brecha para ayudar a decidir si hay que notificar y Comunica-Brecha para la comunicación a los interesados, además de su guía de notificación. El plazo empieza a contar cuando tienes constancia, no cuando terminas de investigar, y la notificación puede hacerse por fases. El inventario del paso 1 y las capturas de tráfico del paso 3 son exactamente lo que te va a pedir la notificación. Y si leíste mi último artículo, sabrás que la AEPD ya ha recibido su primera notificación de una brecha ejecutada por un agente de IA. Que un agente provoque una brecha publicando datos es un caso distinto de que un agente te ataque, pero el regulador está claramente atento a ambos.

Cómo evaluar el uso de tokens en el panel de OpenAI

Si se filtró una clave de OpenAI, necesitas tres respuestas: si se usó después del push, para qué, y si alguien la usó para crear más accesos.

El panel de uso. En platform.openai.com/usage (propietarios de la organización o usuarios con el permiso Usage Dashboard), la barra superior fija el alcance: orígenes de API, proyecto, claves de API y rango de fechas. Elige el proyecto afectado, acota a la clave filtrada con el selector de claves y ajusta el rango para cubrir una semana de referencia anterior al push y todo lo posterior. Los datos se muestran en UTC, y las páginas de detalle permiten bajar a intervalos de 1 minuto, que es donde el abuso aparece como un muro de tokens a las tres de la mañana. Dos partes de la página importan sobre todo en un incidente. La pestaña API capabilities muestra una tarjeta por servicio (Responses and Chat Completions, Images, Web Searches, File Searches, Moderation, Embeddings y más), así que una clave que solo había hecho texto y de pronto muestra peticiones de imágenes salta a la vista. El panel de la derecha desglosa las peticiones por usuario, servicio y clave de API, y muestra el gasto del mes frente a tu presupuesto. El botón de descarga exporta los datos para el expediente del caso.

srf_agentleak_openai_usage
Figura 2. El panel de uso de OpenAI, filtrado a un proyecto durante 30 días. Revisa todas las tarjetas de la pestaña API capabilities, no solo Responses and Chat Completions: el abuso suele aparecer en un servicio que tu aplicación nunca usa. El panel de la derecha reparte las peticiones por usuario, servicio y clave de API, y muestra el gasto frente al presupuesto mensual. Nombres de organización y de usuario ocultos.

Cifras por clave con la Usage API. El panel sirve para echar un vistazo; como prueba, usa la Usage API con una clave de administración, que permite agrupar por api_key_id, project_id, model y más:

curl "https://api.openai.com/v1/organization/usage/completions?\
start_time=UNIX_TIMESTAMP&bucket_width=1h&group_by=api_key_id&group_by=model&limit=168" \
  -H "Authorization: Bearer $OPENAI_ADMIN_KEY"

Obtienes input_tokens, output_tokens, input_cached_tokens y num_model_requests por intervalo, por clave y por modelo. Hay endpoints separados para embeddings, imágenes, audio, búsqueda web y más, y /v1/organization/costs da el gasto. Revísalos todos: un atacante que queme tu clave generando imágenes no aparecerá en completions.

srf_agentleak_openai_spend
Figura 3. La pestaña Spend categories reparte el coste por modelo entre entrada en caché, entrada y salida, más llamadas a herramientas como la búsqueda web. Un salto en el coste de salida respecto al de entrada es una de las señales que describo más abajo. Nombres de organización y de usuario ocultos.

¿Cuándo se usó la clave por última vez? La página de claves de API lo responde directamente: cada clave tiene una columna Last used junto a su fecha de creación, caducidad, creador y permisos, y el botón API Key Usage, en la parte superior de la página, enlaza con el uso. La Admin API expone el mismo dato como last_used_at en el objeto de clave de proyecto. Si la fecha es posterior a tu rotación, has rotado la clave equivocada. Si una clave de la que te habías olvidado muestra uso reciente, empieza por ahí.

srf_agentleak_openai_apikeys
Figura 4. La página de claves de API de OpenAI. La columna Last used es la respuesta más rápida a «¿se usó esta clave después de la filtración?». Fíjate en la columna Expires con el valor Never: una clave filtrada sin caducidad sigue siendo válida hasta que alguien la rote. Nombres de claves, IDs de seguimiento, fragmentos de clave y creador ocultos.

¿Alguien creó más accesos? Para eso está la Audit Logs API: creación, modificación y borrado de claves de API, cambios de usuarios y cuentas de servicio, inicios de sesión fallidos, cambios de proyectos y de configuración, con tipos de evento como api_key.created. La pega: el registro de auditoría solo recoge datos desde el momento en que un propietario lo activa (configuración de la organización → Data controls → Data retention), y una vez activado no se puede desactivar sin contactar con soporte. Si no estaba activado antes del incidente, no tienes historial. Actívalo hoy.

¿Qué pidieron? Las llamadas a la Responses API se almacenan 30 días por defecto salvo que tu organización tenga Zero Data Retention, y puedes consultarlas en Logs, dentro del panel, con pestañas separadas para Responses, Agents, Realtime, Completions, Conversations y más. Filtra por la ventana de exposición y busca prompts, modelos o herramientas que no reconozcas. Al abrir una entrada ves su marca de tiempo, el modelo, el número de tokens y las herramientas que usó, y muchas veces eso basta para distinguir el tráfico de tu aplicación del de otro. El propio panel avisa ya de que los registros de Responses de más de 30 días dejarán pronto de estar disponibles, así que exporta lo que necesites el primer día. Más allá de eso, OpenAI conserva registros de monitorización de abusos hasta 30 días; si necesitas contenido o datos de origen que no puedes ver, abre un caso en el centro de ayuda cuanto antes, antes de que se cierre esa ventana.

srf_agentleak_openai_logs
Figura 5. La página Logs, pestaña Responses: una fila por llamada almacenada, con su modelo y su marca de tiempo. Lee el aviso: los registros de más de 30 días van a desaparecer, así que exporta pronto. Texto de los prompts oculto.

srf_agentleak_openai_log_detail
Figura 6. Una respuesta registrada. El panel de propiedades da la marca de tiempo, el modelo, el número de tokens y las herramientas usadas (aquí, búsqueda web): el detalle por petición que los gráficos de uso no pueden darte. Prompt e ID de respuesta ocultos.

Cómo evaluar el uso de tokens en la consola de Anthropic

Las preguntas son las mismas; las herramientas cambian.

Mira primero el correo. Si el escaneo de socios de GitHub detectó la clave, Anthropic ya la habrá desactivado y te habrá escrito. Ese correo te da un límite superior de la ventana de exposición de esa clave.

Las páginas de la consola. En Analytics, la consola tiene las páginas Usage y Cost. Ambas trabajan en UTC, filtran por workspace, clave de API y modelo, agrupan el gráfico por modelo y exportan los datos con el botón de descarga; Usage permite filtrar además por cuenta. La propia Anthropic recomienda revisar con regularidad los patrones de uso de cada clave. Durante un incidente, selecciona la clave filtrada, ajusta el rango a tu semana de referencia y la ventana de exposición, y agrupa por modelo. Usage te da los tokens de entrada y de salida; Cost reparte el dinero entre tokens, búsqueda web, ejecución de código y tiempo de sesión. En el mismo menú Analytics hay también una página Logs. No he encontrado documentación pública de lo que registra, así que ábrela al principio del incidente y comprueba si cubre la ventana que necesitas.

srf_agentleak_claude_usage
Figura 7. La página Usage de la consola de Claude durante 30 días, agrupada por modelo. Selecciona la clave filtrada en el filtro API key y compara la ventana de exposición con los días anteriores al push.

srf_agentleak_claude_cost
Figura 8. La página Cost usa los mismos filtros y reparte el gasto entre tokens, búsqueda web, ejecución de código y tiempo de sesión. Si en la leyenda aparece un modelo que tu equipo no usa, merece una mirada más atenta.

Consultar un mes anterior. La columna Cost de la página de claves de API solo cubre el mes en curso. El día 1 se queda en blanco, y una clave que tuvo mucha actividad el mes anterior de repente parece sin uso. Para ver un mes anterior, abre Cost, pon Range en Last month (las flechas de al lado retroceden mes a mes) y cambia el gráfico a la vista de tabla para ver el detalle día a día. El botón de descarga exporta ese mismo periodo desglosado por clave, día, modelo y tipo de token, con el ID y el estado de cada clave. La Cost API no te da eso, porque solo agrupa los costes por workspace o por modelo, así que haz de esta exportación una de las primeras cosas que guardes.

srf_agentleak_claude_cost_lastmonth
Figura 9. La página Cost con Last month en vista de tabla: una fila por día, una columna por modelo y el total facturado. Usa las flechas junto a Range para retroceder hasta el mes de la filtración.

Resumida por clave, esa exportación de una de mis propias cuentas para septiembre queda así (nombres de clave sustituidos):

Clave Estado Coste en septiembre Días con gasto Primer y último día
Clave A Desactivada 104,87 $ 17 7 → 25 sept.
Clave B Activa, creada el 25 sept. 21,49 $ 4 25 → 30 sept.
Clave C Activa 10,98 $ 5 9 → 18 sept.
Clave D Activa 0,11 $ 2 7 → 14 sept.
Total 137,45 $

Hay dos cosas que leer en ella. La clave A, ya desactivada, deja de gastar el 25 de septiembre, el mismo día en que se crea la clave B, que empieza a gastar. Ese es el patrón que quieres ver tras una rotación: la clave antigua se para el día en que la desactivas y la nueva toma el relevo. Una clave desactivada que sigue mostrando gasto después de esa fecha significa que desactivaste la clave equivocada o que no está realmente muerta. La segunda es la mezcla: unos dos tercios del mes (unos 89 $) se fueron en escrituras en la caché de prompts, algo normal en un agente que trabaja con contextos largos. Tu mezcla habitual de tipos de token es una huella de tu propia carga de trabajo, y alguien que abuse de una clave robada con prompts cortos y sin caché dejaría una muy distinta.

Cifras por clave con la Usage and Cost API. Con una clave de la Admin API (sk-ant-admin01-…, que crean los administradores de la organización), el informe de uso agrupa por api_key_id, workspace_id, model y más, en intervalos de 1 minuto, 1 hora o 1 día, y los datos suelen aparecer unos cinco minutos después de la petición:

curl "https://api.anthropic.com/v1/organizations/usage_report/messages?\
starting_at=2026-09-01T00:00:00Z&ending_at=2026-09-25T00:00:00Z&\
bucket_width=1h&group_by[]=api_key_id&group_by[]=model" \
  -H "anthropic-version: 2023-06-01" \
  -H "x-api-key: $ANTHROPIC_ADMIN_KEY"

La respuesta separa uncached_input_tokens, cache_read_input_tokens, cache_creation_input_tokens, output_tokens y el uso de herramientas de servidor. /v1/organizations/cost_report da el dinero. Si tus desarrolladores usan Claude Code dentro de la organización, la Claude Code Analytics API desglosa el coste por usuario.

Desactiva e inventaría las claves. En la consola, Organization settings → API keys lista todas las claves con su cuenta vinculada, workspace, caducidad, creador y coste, y permite filtrar por creador, cuenta vinculada, estado y workspace. El menú al final de cada fila desactiva una clave y, más tarde, permite reactivarla o borrarla. La Admin API hace lo mismo de forma programática: lista las claves y permite poner su estado en inactive o archived. No puede crear claves, así que si tu inventario muestra una clave que nadie reconoce, se creó desde la consola, lo que apunta a una cuenta comprometida más que a una clave filtrada. Eso cambia el alcance del incidente.

srf_agentleak_claude_apikeys
Figura 10. Organization settings → API keys en la consola de Claude. La fila atenuada es una clave desactivada; su menú ofrece reactivarla o borrarla. Los filtros Created by y Status ayudan a detectar claves que nadie recuerda haber creado, y la columna Expires muestra cuáles caducarán solas. Nombres de claves, fragmentos de clave, cuentas vinculadas y creadores ocultos.

Quién cambió qué. El Activity Feed de la Compliance API, accesible con una clave de la Admin API de la consola allí donde la Compliance API esté habilitada para tu organización, registra acciones administrativas como crear una clave de API o añadir un miembro a un workspace. Anthropic deja claro que no registra la actividad de inferencia, así que te dirá si alguien creó accesos, no qué le preguntó al modelo. Para preguntas a nivel de petición, acude al soporte de Anthropic.

Leer las cifras como un investigador

Ningún proveedor te pone una etiqueta de «atacante». Buscas uso que no encaje con tu propio patrón, así que compara siempre la ventana de exposición con una referencia anterior al push. Las señales que busco:

  • Tráfico en una clave después de su hora de rotación, o en una clave que debería estar inactiva (una clave de desarrollo, una clave de un proyecto antiguo).
  • Modelos que tu equipo no usa, sobre todo los más caros, o servicios nuevos (imagen, audio, batch) en una clave que solo hacía texto.
  • Un salto en los tokens de salida respecto a los de entrada, que parece generación masiva y no el patrón habitual de tu aplicación.
  • Actividad a horas, o a un ritmo constante de máquina, que no encaja con la jornada de nadie.
  • Claves, cuentas de servicio, miembros o workspaces nuevos que no creaste, en cualquiera de los dos registros de auditoría.

Lo que ningún panel te va a dar es una IP de origen. El uso se agrega por clave, modelo y tiempo, no por quién llama. Si necesitas atribuir o demostrar un acceso, eso es una petición a soporte, y el tiempo corre.

Cómo evitar el siguiente

La contención es lo urgente. La causa raíz casi siempre es la misma: el agente tenía más alcance del que su tarea necesitaba. Las correcciones no son exóticas:

Quítale al agente la capacidad de publicar. No debería tener una credencial que pueda hacer push a un remoto público, cambiar la visibilidad de un repositorio o crear repositorios. Usa un token con permisos granulares (fine-grained) limitado al repositorio en el que trabaja y exige la aprobación de una persona para git push y para todo lo que toque la visibilidad (todo agente de programación serio admite reglas de denegación o confirmaciones para comandos concretos).

Mantén los secretos fuera del directorio de trabajo del agente. Nada de ficheros .env con claves de producción donde el agente pueda leerlos, nada de claves de administración en su entorno. Si no puede leer el secreto, no puede publicarlo.

Activa la protección de push y el escaneo antes del commit. La protección de push de GitHub y un hook de gitleaks antes del commit habrían bloqueado muy probablemente la parte de los tokens de este incidente antes de que llegara a GitHub, siempre que esos tipos de token estén entre los patrones que reconocen. No habrían detectado una hoja de cálculo con datos personales, y por eso los dos primeros controles importan más.

Acota y pon tope a tus claves de IA. Una clave por proyecto y entorno, presupuestos y límites de gasto configurados, y claves de administración solo para quien las necesita. Una clave de proyecto filtrada con tope de gasto es una molestia; una clave de administración filtrada es un incidente.

Guarda las pruebas más tiempo del que viene configurado por defecto. Amplía la retención de transcripciones del agente (30 días es poco para una investigación que empieza el día 25) y activa ya el registro de auditoría de OpenAI y la recogida del Activity Feed de Anthropic, ahora que no tienes nada que investigar.

La lista de comprobación

Para el día que te toque, en orden:

  1. Mata la sesión del agente y revoca su credencial de git.
  2. Copia las transcripciones del agente, el historial de la shell, el repositorio local y el reflog; calcula sus hashes.
  3. Clona en espejo el repositorio público, analiza todo el historial y construye el inventario de secretos y datos personales.
  4. Rota todos los secretos, primero las claves de administración, y comprueba que las antiguas están muertas.
  5. Haz capturas del tráfico, los forks y las estrellas; después pon el repositorio en privado.
  6. Reescribe el historial con git-filter-repo, contacta con el soporte de GitHub y pide la retirada en los forks conocidos.
  7. Extrae los registros del proveedor de cada secreto filtrado: uso, auditoría, actividad. Para las claves de IA, usa los paneles y las API de arriba.
  8. Haz la evaluación RGPD, notifica en las 72 horas desde que tuviste constancia si procede y documéntalo en cualquier caso.
  9. Corrige los permisos del agente antes de volver a ponerlo en marcha.

En resumen

La lección incómoda de este caso es que nadie hizo nada malicioso y, aun así, terminó en una brecha con consecuencias regulatorias. Llevamos dos años preocupados por que los agentes se vuelvan contra nosotros mediante inyección de prompts y herramientas envenenadas. Esas amenazas son reales. Pero el fallo más común es más simple: le dimos a un programa las mismas credenciales y el mismo alcance que a un ingeniero sénior, sin nada de su criterio, y lo pusimos a correr contra una fecha de entrega.

Todo equipo que use agentes de programación debería ensayar este incidente antes de que ocurra. Elige un repositorio de pruebas, planta un canary token, deja que el agente lo suba y mide cuánto tardas en rotar, auditar y responder a las preguntas del regulador. Si hoy, sin nada ardiendo, no sabes leer el uso de tu proveedor de IA por clave, no lo vas a aprender a las dos de la mañana con el reloj de 72 horas en marcha.

Mantente paranoico. Rota primero. Y nunca le des a un agente un push que no necesita.

Lecturas recomendadas:

¿Preguntas o comentarios? Contacta a través de:

Contacto: info@vulnex.com

Esta entrada fue publicada en AI, Economia, IA, Privacidad, Seguridad, Tecnologia y etiquetada , , , , , , . Guarda el enlace permanente.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.