Módulo 13 de 14

Módulo 13: Detección, respuesta e IA en la sombra

Módulo 13: Detección, respuesta e IA en la sombra

Cada módulo anterior de este curso ha dejado un fragmento de registro sin coserlo al resto: el módulo 6 definió qué queda escrito cuando un agente invoca una herramienta, el módulo 9 propuso tres señales para distinguir uso intensivo legítimo de abuso sistemático, el módulo 11 pidió guardar la versión exacta de modelo y de prompt que respondió a cada petición. Este módulo junta esas piezas en un único registro operativo y le da un propósito concreto: que alguien, en un centro de operaciones de seguridad, pueda mirar ese registro y decidir si algo va mal, y que alguien más, cuando ya ha ido mal, pueda reconstruir con precisión qué pasó.

Lo que hace distinta a una aplicación con modelo de lenguaje no es que necesite telemetría (cualquier aplicación la necesita), es que el propio dato que hay que registrar es a la vez el material de trabajo del atacante y el contenido más sensible que produce la aplicación: el texto que un usuario escribió, el documento que se recuperó para responderle, la instrucción que un agente ejecutó en su nombre. Diseñar ese registro bien, y responder con él cuando algo se filtra, es el trabajo que desarrolla este módulo.

Qué aprenderás

  • Qué campos concretos hay que conservar de una aplicación con modelo (prompt, documentos recuperados, herramientas invocadas, decisiones de guardrail, identidad, versión de modelo y de prompt, consumo) y por qué cada uno importa para la detección.
  • Cómo se concilia la necesidad de investigar con la obligación de minimizar datos personales, con seudonimización, campos separados y ventanas de retención distintas según el uso.
  • Seis patrones de abuso concretos de una aplicación con modelo y qué campo exacto del registro delata cada uno.
  • Los pasos propios de responder a un incidente en el que un asistente ha filtrado datos: qué cortar primero, cómo acotar el alcance con los registros, cuándo hay una brecha notificable.
  • Por qué un modelo no determinista convierte «vuelve a ejecutarlo» en una prueba inútil, y qué hay que haber guardado de antemano para no depender de repetir nada.
  • Qué es la IA en la sombra, qué rastro deja en la red y en el punto final, y qué política reduce su uso en vez de empujarlo a la clandestinidad.
  • Por qué un inventario de aplicaciones con IA es el control que hace posible todo lo anterior, y en qué se diferencia del registro de modelos del módulo 7.
  • A diseñar el esquema de registro de una aplicación propia, con sus campos, su retención y su nivel de sensibilidad, y a escribir la lógica de una detección sobre ese registro.

Qué queda en el registro de una aplicación con modelo

Ningún campo de esta lista es una novedad de este módulo por sí solo: cada uno ya apareció, con su propio desarrollo, en un módulo anterior. Lo que aporta este apartado es juntarlos en un único evento y explicar por qué la ausencia de cualquiera de ellos deja un punto ciego que ningún otro campo compensa.

El prompt del usuario, o al menos una versión minimizada de él, es el punto de partida de casi cualquier investigación: sin él no hay forma de distinguir una petición legítima de un intento de inyección de prompt de los que desarrolló el módulo 3. Los documentos recuperados, con su identificador y su ámbito de acceso tal como los definió el módulo 5, permiten comprobar después si lo que vio el modelo debía estar al alcance de quien preguntó. Las herramientas invocadas y sus argumentos exactos, con el formato que ya fijó el registro de acciones del agente del módulo 6, son lo único que distingue una consulta de lectura inocua de una transferencia de dinero. Las decisiones de guardrail (qué se bloqueó, en qué punto del flujo y con qué motivo, según la taxonomía de entrada, salida y herramientas que desarrolló el módulo 11) son la señal más barata de calcular de todo el registro, porque ya las calculó la propia aplicación al aplicar el control. La identidad de quien hizo la petición, propagada según el mecanismo que construyó el módulo 10, permite agrupar eventos por quién los generó sin depender de una IP que cambia de sesión en sesión. La versión de modelo y de prompt que respondió, la misma pareja que pidió el módulo 11 para poder repetir una evaluación, es la que responde a la pregunta «¿qué combinación exacta generó esta respuesta?» cuando ya hay un incidente abierto. Y el consumo, en tokens de entrada y de salida, es la base numérica de la detección de picos que desarrolló el módulo 9.

Un evento que junta los siete campos, con nombres coherentes con los que ya usaron los módulos anteriores de este curso, tiene esta forma:

{
  "ts": "2026-07-30T09:31:00Z",
  "identidad_pseudonima": "u-9c31",
  "sesion_id": "s-002",
  "origen": {"ip_hash": "a1f0...", "pais": "ES"},
  "modelo": "proveedor-x/modelo-y:2026-06",
  "prompt_version": "soporte-cliente/v4",
  "prompt_usuario_minimizado": "consulta sobre pedido [ID_PEDIDO]",
  "documentos_recuperados": [
    {"id": "doc-4471", "ambito": "ventas-es"}
  ],
  "herramienta": "consultar_pedido",
  "argumentos": {"id_pedido": "4511"},
  "guardrail_entrada": {"resultado": "permitido"},
  "guardrail_salida": {"resultado": "permitido"},
  "tokens_entrada": 120,
  "tokens_salida": 180
}

Ningún campo de este evento sustituye al registro de acciones del agente del módulo 6, que sigue siendo la fuente de verdad para lo que un agente ejecutó y quién lo confirmó. Este evento es una capa por encima, pensada para correlacionar entre módulos: agrupa por identidad_pseudonima y sesion_id lo que hasta ahora vivía disperso en el registro de acciones, en el banco de evaluación y en el contador de tokens de cada llamada.

El conflicto entre investigar y minimizar, y cómo se resuelve

El módulo 4 de este curso ya planteó este conflicto desde el lado de la protección de datos, con el artículo 5 del RGPD y el calendario del artículo 12 y el artículo 19 del Reglamento europeo de IA tras el aplazamiento del Reglamento (UE) 2026/1744. Aquí no se repite esa base legal, se retoman sus tres consecuencias prácticas y se aplican al registro que acaba de definir la sección anterior, porque ese es justo el punto en el que un principio de protección de datos deja de ser una frase en un documento y pasa a ser una decisión de diseño de un campo concreto.

La primera consecuencia es la seudonimización. No consiste en borrar la identidad de cada evento, consiste en sustituirla por una referencia que solo un proceso autorizado puede resolver de vuelta al usuario real: el campo identidad_pseudonima del evento anterior no es el correo ni el nombre de quien preguntó, es un token estable que permite agrupar todos sus eventos entre sí sin que quien analiza patrones de abuso necesite ver, a la vez, quién es. La tabla de correspondencia entre ese token y la identidad real vive en un sistema aparte, con su propio control de acceso y su propio registro de quién la consultó, exactamente el mismo principio de campos separados que ya propuso el módulo 4.

La segunda es la propia separación de campos, llevada un paso más allá de lo que basta para seudonimizar: el contenido textual del prompt (el campo más sensible y menos necesario para la mayoría de detecciones) puede vivir en un almacén distinto del de los metadatos estructurados (modelo, versión, tokens, decisión de guardrail), con permisos de lectura distintos para cada uno. Un analista construyendo una regla de detección de picos de consumo necesita el segundo almacén casi siempre; solo necesita el primero cuando ya hay un caso abierto que justifique leer el contenido real de una conversación.

La tercera es la retención por capas que ya propuso el módulo 4: una ventana corta para el contenido textual completo, útil mientras un incidente reciente todavía se puede investigar con detalle, y una ventana mucho más larga para las métricas agregadas (recuentos de tokens por identidad y día, número de bloqueos de guardrail por semana) que ya no permiten identificar a nadie y que son las que alimentan una detección de tendencia a largo plazo, del tipo que necesita la sección de picos de consumo de este mismo módulo. NIST recoge la misma idea, sin ser específico de plazos, en su perfil de IA generativa: entre las técnicas para reducir el riesgo de vincular información generada por IA con una persona concreta cita explícitamente la anonimización, la privacidad diferencial y otras tecnologías de mejora de la privacidad, la misma familia de herramientas que ya trató el módulo 9 al hablar de sus límites frente a la extracción de modelo.

Casos de detección: qué campo delata cada patrón

Las seis situaciones siguientes no agotan lo que se puede detectar sobre una aplicación con modelo, son las que tienen una firma propia de este tipo de aplicación, distinta de cualquier regla que ya escriba un centro de operaciones sobre tráfico web convencional. Cada una señala qué campo del evento de la sección anterior la hace visible; escribir la regla de correlación que convierte ese campo en una alerta accionable, con su propio umbral y su propia tasa de falsos positivos, es el trabajo que desarrolla en profundidad el curso de ingeniería de detección para SOC de este centro.

Intentos repetidos de extracción del prompt de sistema

El módulo 3 y el módulo 8 de este curso ya desarrollaron cómo se extrae un prompt de sistema: pidiéndolo de forma directa, o reconstruyéndolo por caja negra observando qué bloquea el modelo sin ver una sola línea de su texto. Un intento aislado no distingue a un atacante de un usuario curioso probando los límites de la aplicación. Lo que sí lo distingue es la repetición: varias formulaciones distintas de la misma petición, en una ventana de tiempo corta, desde la misma identidad, todas resueltas por el mismo motivo de bloqueo. El campo que lo delata es guardrail_salida.motivo, agregado por identidad_pseudonima dentro de una ventana deslizante; tres bloqueos por el mismo motivo en quince minutos pesa de forma muy distinta que uno solo en una semana.

Invocación anómala de herramientas

El registro de acciones del módulo 6 ya captura qué herramienta se llamó y con qué argumentos. Lo que falta ahí es un punto de comparación: qué herramientas invoca habitualmente esa identidad, o ese rol, y si la llamada de ahora se sale de ese patrón. La iniciativa de seguridad agéntica de OWASP dedica su entrada ASI10, «Rogue Agents», precisamente a esta idea: un agente que empieza a actuar fuera de su función prevista, con acciones que por separado pueden parecer legítimas pero cuyo patrón se sale de lo esperado. Sus mitigaciones piden desplegar detección de comportamiento, con vigilancia sobre picos o ejecuciones de acciones anómalas, y mecanismos de contención rápidos (interruptores de corte y revocación de credenciales) para desactivar al agente en cuanto salta la alarma. MITRE ATLAS recoge la misma idea como técnica, bajo el identificador AML.T0053, «AI Agent Tool Invocation»: un adversario que usa su acceso a un agente para invocar herramientas a las que ese agente tiene acceso, y su variante de exfiltración, AML.T0086, cuando esa invocación se usa para sacar datos hacia un destino controlado por el atacante camuflado en una acción de apariencia legítima, como enviar un correo o modificar un documento. El campo que delata esto es herramienta, comparado contra el conjunto de herramientas ya observadas para ese rol; el ejercicio de este módulo construye esa comparación paso a paso.

Recuperación de documentos fuera del ámbito habitual

El módulo 5 desarrolló entero el problema de que un índice de recuperación no hereda permisos por sí solo, y el filtrado por permisos en el momento de la consulta como la solución que sí funciona. La detección es la comprobación posterior a ese control: si el filtro falló, o si alguien con acceso legítimo pero limitado empieza a recuperar de forma sistemática documentos fuera de su departamento habitual, algo digno de mirar está pasando, aunque cada recuperación individual esté técnicamente autorizada. El campo que lo delata es documentos_recuperados[].ambito, comparado contra el ámbito habitual de esa identidad a lo largo de su historial reciente; una identidad que durante semanas solo recuperó documentos de «ventas-es» y de repente recupera varios de «recursos-humanos» en la misma sesión, aunque el sistema se lo haya permitido, merece una alerta de baja severidad que un analista revise.

Picos de consumo

El módulo 9 ya desarrolló en profundidad las tres señales que distinguen uso intensivo legítimo de abuso sistemático: patrones de uso regulares, entropía de las consultas que cae de golpe, y ritmo de peticiones sin las pausas de una lectura humana. Lo que añade este módulo es solo el campo exacto: tokens_entrada y tokens_salida, agregados por identidad y por ventana de tiempo, comparados contra la línea base histórica de esa misma identidad, no contra un umbral fijo igual para toda la base de usuarios. Una identidad que multiplica por diez su consumo medio de un día para otro, aunque cada petición individual pase cualquier validación de entrada, es la señal más barata de calcular de las seis que reúne esta sección.

Salidas bloqueadas en serie

El módulo 11 organizó los guardrails en tres puntos de control (entrada, salida y herramientas) y explicó cómo medirlos con las cuatro casillas de un clasificador: bloqueos correctos, permisos correctos, falsos positivos y falsos negativos. Una racha de bloqueos consecutivos de salida sobre la misma identidad admite dos lecturas, y las dos merecen investigarse: puede ser un atacante insistiendo con variaciones de la misma petición hasta encontrar una que el guardrail no cubra, o puede ser el guardrail mismo funcionando mal tras un cambio reciente de prompt o de modelo, bloqueando de forma sistemática algo que debería pasar. El campo que lo delata es guardrail_salida.resultado, contando bloqueos consecutivos por identidad; distinguir cuál de las dos lecturas es la correcta pasa por mirar si la racha empezó justo después de un despliegue nuevo (apunta a guardrail roto, y hay que revisar el banco de evaluación del módulo 11) o si coincide con variaciones deliberadas del texto de entrada (apunta a un intento activo).

Uso desde orígenes imposibles

Esta es la única de las seis que no depende de nada específico del modelo: es la misma lógica de «viaje imposible» que cualquier centro de operaciones ya aplica a un inicio de sesión convencional, trasladada a la identidad que propagó el módulo 10 hasta la propia llamada al modelo. Si la misma identidad, o la misma credencial de servicio de las que desarrolló ese módulo, genera peticiones desde dos países sin conexión de red razonable entre sí en una ventana de minutos, algo no cuadra, sea una credencial robada, un token reutilizado fuera de su audiencia esperada, o una integración mal configurada que reenvía tráfico por un proxy inesperado. El campo que lo delata es origen.pais (o el atributo geográfico que use la aplicación), cruzado con identidad_pseudonima y con la marca de tiempo de cada evento. El propio módulo 10 ya señaló que detectar un token reutilizado fuera de su audiencia es trabajo de telemetría continua; este es el caso concreto de esa telemetría aplicado a la capa de origen de la petición.

Caso Campo que lo delata Módulo que desarrolla el mecanismo de fondo
Extracción repetida del prompt de sistema guardrail_salida.motivo, agregado por identidad en una ventana corta Módulo 3 (inyección) y módulo 8 (filtración de prompts)
Invocación anómala de herramientas herramienta, comparada contra el patrón habitual del rol Módulo 6 (registro de acciones del agente)
Recuperación fuera de ámbito documentos_recuperados[].ambito, comparado contra el ámbito habitual Módulo 5 (control de acceso en RAG)
Picos de consumo tokens_entrada / tokens_salida, contra la línea base propia Módulo 9 (consumo y extracción)
Salidas bloqueadas en serie guardrail_salida.resultado, bloqueos consecutivos por identidad Módulo 11 (guardrails y su medición)
Orígenes imposibles origen.pais cruzado con identidad y marca de tiempo Módulo 10 (propagación de identidad)

Respuesta a un incidente: el asistente ha filtrado datos

El curso de DFIR de este centro desarrolla el proceso general de respuesta a incidentes (contención, erradicación, recuperación, lecciones aprendidas) que se aplica sin cambios a este dominio. Lo que añade este módulo son los cuatro pasos específicos de una aplicación con modelo, en el orden en que suelen ejecutarse cuando la alerta llega desde alguno de los seis casos de la sección anterior.

El primero es cortar la herramienta o el índice implicado, no la aplicación entera si se puede evitar. Si la alerta señala una herramienta concreta invocada fuera de patrón, desactivar esa herramienta (o revocar la credencial con la que actuaba, siguiendo la misma lógica de contención rápida que propuso ASI10 de OWASP para agentes descontrolados) detiene el daño sin apagar el resto de la aplicación. Si la alerta señala un índice de recuperación envenenado o filtrando fuera de su ámbito, retirar ese índice de la ruta de consulta mientras se investiga tiene el mismo efecto sin tocar el resto del sistema.

El segundo es determinar el alcance con los registros, no con la memoria de nadie. El evento de la primera sección de este módulo, con su identidad, su ventana de tiempo y sus documentos recuperados, es lo que permite responder con precisión a la pregunta que abre cualquier investigación: qué vio exactamente quien atacó, durante cuánto tiempo, y si hubo más de una identidad implicada. Sin ese registro, esta pregunta se responde por aproximación, y una aproximación es una base débil para decidir a quién hay que notificar.

El tercero es valorar si hay una brecha de datos personales notificable. Esta valoración no es un juicio técnico que haga quien investigó el incidente en solitario: necesita el mismo criterio legal que aplicaría cualquier otra brecha de la organización, y ese criterio, junto con los plazos y los destinatarios de la notificación, es contenido propio del curso de gobierno, riesgo y cumplimiento de este centro. Lo específico de una aplicación con modelo es que el alcance de esa valoración depende directamente de lo bien que respondiera el paso anterior: sin saber qué documentos o qué datos vio el atacante, no hay forma de decidir si lo que se filtró incluye datos personales de terceros.

El cuarto es corregir, y aquí es donde este módulo se conecta con el módulo 11: la corrección va más allá de cerrar el agujero concreto que se explotó: incluye añadir el caso al banco de evaluación que ya desarrolló ese módulo, para que la próxima vez que cambie el prompt, el modelo o el guardrail, una regresión sobre este mismo ataque salte antes de llegar a producción. Un incidente que no deja un caso de prueba nuevo detrás es una lección que la organización va a tener que volver a aprender.

Por qué «vuelve a ejecutarlo» no es una prueba válida

Cualquier investigación forense sobre software convencional puede, en el peor de los casos, volver a ejecutar el mismo binario con la misma entrada y esperar el mismo resultado. Con un modelo de lenguaje esa suposición falla, y falla por un motivo más profundo de lo que parece a primera vista.

La explicación intuitiva (que la aleatoriedad viene del muestreo por temperatura, y que fijarlo a cero soluciona el problema) es cierta solo en parte. Un análisis técnico de Thinking Machines Lab, publicado el 10 de septiembre de 2025, identificó una causa distinta y más difícil de eliminar: buena parte de la falta de reproducibilidad de un servicio de inferencia en producción no viene de la aritmética de coma flotante en sí (los autores muestran que una misma multiplicación de matrices en una GPU da resultados idénticos, bit a bit, en repeticiones sucesivas), viene de que el tamaño del lote con el que el servidor agrupa las peticiones concurrentes varía sin control según la carga del momento. La cita literal del propio análisis es contundente: la razón principal por la que casi cualquier servicio de inferencia de un modelo de lenguaje es no determinista es que la carga, y por tanto el tamaño del lote, varía de forma no determinista. Con un tamaño de lote fijo, usando modelos de pesos abiertos como los de la familia Qwen, la reproducibilidad exacta vuelve; con el procesamiento por lotes de tamaño variable que usa cualquier servicio de producción real, desaparece, aunque la temperatura esté fijada a cero.

La consecuencia forense es directa: la composición exacta del lote en el que se procesó una petición concreta depende de qué otras peticiones de otros usuarios llegaron en ese mismo instante, un estado que no queda registrado en ningún sitio y que es, en la práctica, irrepetible. Fijar la temperatura y una semilla ayuda a acercarse a un comportamiento estable, pero ninguna de las dos garantiza, por sí sola, reproducir de forma exacta la respuesta original. Por eso «vuelve a ejecutarlo y mira qué pasa» no es un procedimiento de investigación válido sobre una aplicación con modelo: lo que salió la primera vez es, en un sentido literal, un evento que ya no se puede reconstruir generándolo de nuevo.

Lo que sí permite reconstruir qué pasó es haberlo guardado desde el principio, con el mismo evento que definió la primera sección de este módulo: el texto exacto de la respuesta generada (no solo el prompt que la provocó), la versión exacta de modelo y de prompt que la produjo, la marca de tiempo, y cualquier documento recuperado que formara parte del contexto. Con esos cuatro datos, la pregunta de investigación deja de depender de repetir nada: se responde leyendo lo que ya quedó escrito.

IA en la sombra

Todo lo anterior de este módulo asume una aplicación que la propia organización construyó y de la que controla el registro. La IA en la sombra es el escenario contrario: empleados usando herramientas de IA no aprobadas, con datos de la empresa, sin que exista ningún registro propio porque la aplicación ni siquiera es de la organización.

La magnitud del fenómeno tiene, al fin, un dato con metodología sólida detrás y no solo una encuesta de marketing de un proveedor de seguridad. El informe de investigación de brechas de datos (DBIR) de Verizon de 2026, publicado el 19 de mayo de 2026, señala que el uso frecuente de herramientas de IA no aprobadas por parte de empleados se triplicó, de un 15% a un 45%, en un solo año, convirtiendo a la IA en la sombra en la tercera causa más común de fuga de datos de origen no malicioso que el informe identifica. Es un dato que vale la pena tomar en serio precisamente porque no sale de una encuesta de autopercepción sobre intenciones, sale del análisis de incidentes reales que Verizon recopila para el mismo informe cada año.

Detectar este uso desde dentro de la organización no depende de ningún registro propio de aplicación, porque por definición no existe: depende de mirar la red y el punto final. Desde la red, el tráfico saliente hacia dominios conocidos de servicios de IA generativa es visible para cualquier proxy o pasarela que ya inspeccione tráfico web, del mismo modo que ya se vigila cualquier otro destino no autorizado; una pasarela de prevención de pérdida de datos que ya esté desplegada puede extenderse para inspeccionar ese tráfico concreto en busca de patrones de datos sensibles saliendo hacia un destino no corporativo. Desde el punto final, la telemetría de qué aplicaciones y qué extensiones de navegador se ejecutan en un equipo corporativo es la misma que ya usa cualquier programa de gestión de activos para detectar software no autorizado en general, aplicada aquí a una categoría concreta de software.

La política que tiene sentido no es prohibir sin ofrecer nada a cambio. Un análisis de ISACA, publicado el 26 de septiembre de 2025, lo plantea con una secuencia concreta: entender primero qué riesgo crea realmente el uso no aprobado en la organización, publicar después una política que liste las herramientas ya aprobadas, defina qué datos se pueden compartir con cada una y exija formación a quien las use, y mantener un catálogo vivo de herramientas evaluadas y aprobadas como alternativa real. Prohibir un uso sin dar una vía legítima para la misma necesidad no elimina esa necesidad, la traslada a un canal que la organización ya no puede ver, que es exactamente el problema que este apartado trata de resolver, no de reproducir con otro nombre.

El inventario que hace posible todo lo demás

El módulo 7 de este curso ya desarrolló el registro de modelos de la organización: qué modelo exacto, con qué procedencia verificada, sirve cada aplicación en producción. Ese registro responde a una pregunta distinta de la que necesita este módulo, aunque las dos se parezcan de lejos. El registro de modelos cubre los modelos que la organización decidió usar; el inventario de aplicaciones con IA cubre todo punto de contacto con un modelo que exista dentro de la organización, lo haya aprobado alguien o no, incluida cualquier herramienta de IA en la sombra que se descubra por la vía de la sección anterior.

Sin ese inventario, cada apartado de este módulo se queda cojo: no se puede diseñar el registro de la primera sección de una aplicación que nadie sabe que existe, no se puede escribir ninguna de las seis detecciones sobre una aplicación fuera del radar, y no se puede responder a un incidente en un sistema que no aparece en ningún sitio como responsabilidad de nadie. El inventario no sustituye a ningún control de los que ya ha desarrollado este curso, es la lista de dónde aplicarlos todos.

Ejercicio: esquema de registro y dos detecciones

El objetivo de este ejercicio es diseñar el esquema de registro de una aplicación de soporte propia, con sus campos, su retención y su nivel de sensibilidad, y después escribir en Python la lógica de dos de las seis detecciones de este módulo sobre un conjunto de eventos sintético. No hace falta ninguna cuenta de pago ni ningún modelo real: basta con un intérprete de Python 3 instalado en tu equipo.

Primero, el esquema. La tabla siguiente es el resultado de aplicar los tres principios de la sección de minimización a los siete campos que definió este módulo: qué capa de almacenamiento le corresponde a cada uno, cuánto tiempo se conserva, y qué nivel de sensibilidad tiene.

Campo Retención Nivel de sensibilidad
identidad_pseudonima, sesion_id Igual que los metadatos asociados Bajo por sí solo; la tabla de correspondencia con la identidad real, aparte y con acceso restringido
prompt_usuario_minimizado (texto completo o casi completo) Corta: días o pocas semanas, la ventana útil para investigar un incidente reciente Alto: puede contener datos personales pegados por el usuario
modelo, prompt_version, documentos_recuperados[].id Larga: meses, no identifica a nadie por sí solo Bajo
herramienta, argumentos Larga para el nombre de la herramienta; corta para argumentos con datos de negocio sensibles (importes, identificadores de pedido reales) Medio a alto según el argumento concreto
guardrail_entrada, guardrail_salida Larga: es la base de la detección de tendencia Bajo
tokens_entrada, tokens_salida Larga Bajo
origen.pais (agregado; no la IP completa sin necesidad) Larga Bajo si se guarda agregado; alto si se guarda la IP completa sin necesidad

Segundo, genera un conjunto de eventos sintético con la misma forma que el esquema anterior: tres identidades distintas, una con uso normal, una que intenta repetidamente que el modelo revele sus instrucciones, y una cuyo rol solo usaba una herramienta hasta que, en un momento dado, invoca otra con un argumento de importe alto.

import json
from datetime import datetime, timedelta
from collections import defaultdict

base = datetime(2026, 7, 30, 9, 0, 0)

def ev(minutos, identidad, rol, sesion, herramienta=None, argumentos=None,
       guardrail_salida="permitido", motivo_guardrail=None):
    return {
        "ts": (base + timedelta(minutes=minutos)).isoformat(),
        "identidad_pseudonima": identidad,
        "rol": rol,
        "sesion_id": sesion,
        "herramienta": herramienta,
        "argumentos": argumentos,
        "guardrail_salida": guardrail_salida,
        "motivo_guardrail": motivo_guardrail,
    }

eventos = []
for i, m in enumerate([0, 4, 9, 15]):
    eventos.append(ev(m, "u-7a2f", "soporte_nivel1", "s-001",
                       herramienta="consultar_pedido",
                       argumentos={"id_pedido": str(4500 + i)}))

for i, m in enumerate([20, 23, 26]):
    eventos.append(ev(m, "u-9c31", "soporte_nivel1", "s-002",
                       guardrail_salida="bloqueado",
                       motivo_guardrail="posible_fuga_prompt_sistema"))
eventos.append(ev(31, "u-9c31", "soporte_nivel1", "s-002",
                   herramienta="consultar_pedido", argumentos={"id_pedido": "4511"}))

for m in [60, 66, 74]:
    eventos.append(ev(m, "u-4410", "soporte_nivel1", "s-003",
                       herramienta="consultar_pedido", argumentos={"id_pedido": "4520"}))
eventos.append(ev(90, "u-4410", "soporte_nivel1", "s-003",
                   herramienta="aplicar_reembolso",
                   argumentos={"id_pedido": "4520", "importe_centimos": 48000}))

with open("eventos.jsonl", "w", encoding="utf-8") as f:
    for e in eventos:
        f.write(json.dumps(e, ensure_ascii=False) + "n")
print(f"Generados {len(eventos)} eventos")

Tercero, escribe la primera detección: intentos repetidos de extracción del prompt de sistema, agrupando por identidad los bloqueos de guardrail de salida con el mismo motivo dentro de una ventana deslizante.

def detectar_extraccion_prompt(eventos, umbral=3, ventana_minutos=15):
    por_identidad = defaultdict(list)
    for e in eventos:
        if (e["guardrail_salida"] == "bloqueado"
                and e["motivo_guardrail"] == "posible_fuga_prompt_sistema"):
            por_identidad[e["identidad_pseudonima"]].append(
                datetime.fromisoformat(e["ts"]))

    alertas = []
    for identidad, marcas in por_identidad.items():
        marcas.sort()
        for i in range(len(marcas)):
            ventana = [t for t in marcas
                       if marcas[i] <= t <= marcas[i] + timedelta(minutes=ventana_minutos)]
            if len(ventana) >= umbral:
                alertas.append({"identidad_pseudonima": identidad,
                                 "intentos_en_ventana": len(ventana),
                                 "primera_marca": ventana[0].isoformat(),
                                 "ultima_marca": ventana[-1].isoformat()})
                break
    return alertas

Cuarto, escribe la segunda detección: invocación anómala de herramientas, comparando cada llamada posterior a una ventana de entrenamiento contra el conjunto de herramientas ya observadas para ese rol en esa ventana.

def construir_baseline(eventos, hasta_minuto):
    baseline = defaultdict(set)
    for e in eventos:
        minuto = (datetime.fromisoformat(e["ts"]) - base).total_seconds() / 60
        if e["herramienta"] and minuto <= hasta_minuto:
            baseline[e["rol"]].add(e["herramienta"])
    return baseline

def detectar_herramienta_anomala(eventos, baseline, desde_minuto):
    alertas = []
    for e in eventos:
        minuto = (datetime.fromisoformat(e["ts"]) - base).total_seconds() / 60
        if e["herramienta"] and minuto > desde_minuto:
            if e["herramienta"] not in baseline.get(e["rol"], set()):
                alertas.append({"identidad_pseudonima": e["identidad_pseudonima"],
                                 "rol": e["rol"],
                                 "herramienta_nueva_para_el_rol": e["herramienta"],
                                 "argumentos": e["argumentos"],
                                 "ts": e["ts"]})
    return alertas

baseline = construir_baseline(eventos, hasta_minuto=80)
print(detectar_extraccion_prompt(eventos))
print(detectar_herramienta_anomala(eventos, baseline, desde_minuto=80))

Ejecutar este código completo contra los doce eventos generados en el segundo paso produce esta salida real, sin modificar:

[{'identidad_pseudonima': 'u-9c31', 'intentos_en_ventana': 3,
  'primera_marca': '2026-07-30T09:20:00', 'ultima_marca': '2026-07-30T09:26:00'}]
[{'identidad_pseudonima': 'u-4410', 'rol': 'soporte_nivel1',
  'herramienta_nueva_para_el_rol': 'aplicar_reembolso',
  'argumentos': {'id_pedido': '4520', 'importe_centimos': 48000},
  'ts': '2026-07-30T10:30:00'}]

Quinto, y para cerrar el ejercicio con la parte que este script todavía no resuelve: escribe, en un párrafo aparte, con qué umbral y con qué ventana ajustarías cada detección si la aplicaras a tu propio volumen real de tráfico, y qué harías con la alerta de u-4410 del ejemplo anterior (¿la cerrarías sola con el registro disponible, o la escalarías para que alguien confirme si el reembolso de 480 euros fue una acción legítima?). Ese criterio de umbral y de escalado, no el código en sí, es la parte del ejercicio que de verdad reproduce el trabajo de diseñar una detección real, y es la que desarrolla en profundidad el curso de ingeniería de detección para SOC enlazado antes en este módulo.

Preguntas frecuentes

¿Basta con los registros de acceso y de errores que ya genera cualquier aplicación web para investigar un incidente de una aplicación con modelo?

No. Un registro de acceso convencional dice quién llamó a qué endpoint y cuándo, pero no dice qué vio el modelo, qué herramienta invocó en nombre de quién, ni qué versión de prompt generó una respuesta concreta. Sin esos campos específicos, que ya definió la primera sección de este módulo, la investigación se queda en el nivel de red y nunca llega al nivel de qué hizo realmente la aplicación.

¿La seudonimización basta para no tener que tratar este registro como datos con protección legal?

No. Un registro seudonimizado sigue siendo, en la práctica, un registro que permite identificar a alguien si se cruza con la tabla de correspondencia, y por eso sigue sujeto a las mismas obligaciones que desarrolló el módulo 4 de este curso. La seudonimización reduce el riesgo y limita quién necesita acceso al dato completo, no elimina la obligación de tratarlo con cuidado.

¿En qué se diferencia el evento de este módulo del registro de acciones del agente del módulo 6?

El del módulo 6 es la fuente de verdad de qué ejecutó un agente y quién lo aprobó, pensado para auditar una acción concreta. El de este módulo es una capa de correlación por encima, pensada para agrupar eventos de distintos módulos (guardrails, consumo, recuperación) bajo la misma identidad y sesión, con el objetivo de alimentar las detecciones que desarrolla este módulo. Uno no sustituye al otro.

¿Hace falta un SIEM comercial para aplicar lo que enseña este módulo?

No para el diseño del esquema ni para escribir la lógica de una detección, como demuestra el propio ejercicio con Python puro. Para correlacionar volúmenes de producción reales, con miles de eventos por minuto, un sistema centralizado de recogida y consulta de registros deja de ser opcional; el curso de ingeniería de detección para SOC de este centro desarrolla cómo se elige y se opera esa capa.

¿Un pico de bloqueos de guardrail de salida siempre significa un ataque en marcha?

No siempre, y la propia sección de este módulo que trata ese caso lo señala: la misma racha puede ser un guardrail que empezó a fallar tras un cambio de prompt o de modelo, bloqueando de forma sistemática algo que debería pasar. Distinguir las dos lecturas exige mirar si la racha coincide con un despliegue reciente o con variaciones deliberadas de la entrada, no asumir la explicación más alarmante por defecto.

¿Detectar IA en la sombra desde la red basta, o hace falta también vigilar el punto final?

Las dos capas ven cosas distintas. La red ve el tráfico saliente hacia un servicio no aprobado, pero no distingue con precisión qué datos concretos salieron dentro de ese tráfico si va cifrado. El punto final ve qué aplicación o qué extensión de navegador se ejecutó, pero no ve el tráfico si el propio dispositivo no está bajo la gestión de la organización. Ninguna de las dos, por separado, cubre el fenómeno entero.