¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Modelado de amenazas de un agente de IA

Después de esta lección: Puedo mapear dónde se puede atacar a un agente y nombrar la mezcla de tres cosas que lo hace peligroso.

Lección de 65 min8 comandosLaboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

Dónde se ataca a un agente de IA

Un modelo de amenazas lista lo que un atacante podría alcanzar y cómo. Para un agente importa más que para un chat, porque el agente actúa. Lee correo, llama a herramientas y envía cosas al exterior.

El módulo Proteger aplicaciones con LLM te dio la inyección y los riesgos principales. Esta lección los convierte en el mapa de un agente, dibujado antes de escribir código.

Al final de esta lección

Nota

Puedo mapear dónde se puede atacar a un agente y nombrar la mezcla de tres cosas que lo hace peligroso.

Palabras clave

PalabraQué significaEjemplo
Activoalgo que merece protección, como una lista de clientes o una herramienta de pago
Frontera de confianzala línea donde el texto o las llamadas pasan de una fuente que controlas a otra que no
Contenido no fiabletexto que lee el agente y que un desconocido pudo escribiruna página web
Salidacualquier ruta por la que el agente puede enviar datos lejos de su dueño
Patauna de las tres cosas de la mezcla peligrosa

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

La mezcla peligrosa de tres cosas

Tres cosas juntas son peligrosas. El agente tiene datos privados. Lee contenido no fiable. Tiene una salida para enviar datos fuera.

Con dos de las tres, el ataque se atasca. El texto puede dirigir al agente, pero nada sale, o no hay nada privado que llevarse. Con las tres, una sola línea oculta puede sacar datos.

Ejemplo resuelto: tres agentes

AgenteDatos privadosContenido no fiableSalida
Resumen de correoLa bandeja de entradaCorreo de desconocidosNinguna: solo muestra un resumen
Oficinista webNingunoCualquier página webPuede publicar en un chat
Ayuda de bandejaLa bandeja de entradaCorreo de desconocidosPuede enviar respuestas

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

El Run lista patas, no ataca nada

El primer script guarda cuatro agentes inventados como simples datos. Muestra las patas de cada uno y marca los que tienen las tres.

No se llama a ningún modelo ni se hace ningún ataque. Un modelo de amenazas razona sobre lo que es posible, así que una lista en un script basta para practicar.

Escribe el script de las patas, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Cuatro agentes inventados. Cada indicador dice lo que el agente puede hacer.' 'const agents = [' '  { name: \"resumen-correo\", data: true, untrusted: true, out: false },' '  { name: \"oficinista-web\", data: false, untrusted: true, out: true },' '  { name: \"robot-informes\", data: true, untrusted: false, out: true },' '  { name: \"ayuda-bandeja\", data: true, untrusted: true, out: true },' '];' > legs.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el script de las patas, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function legs(a) {' '  const found = [];' '  if (a.data) found.push(\"datos privados\");' '  if (a.untrusted) found.push(\"contenido no fiable\");' '  if (a.out) found.push(\"una salida\");' '  return found;' '}' 'for (const a of agents) {' '  const all = legs(a).length === 3;' '  console.log(a.name + \": \" + legs(a).join(\", \") + (all ? \"  <- las tres\" : \"\"));' '}' >> legs.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecuta el script de las patas

Comando
docker exec -w /home/node/project agent node legs.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Lo que imprime el script

LíneaLo que muestra
resumen-correo: datos privados, contenido no fiableDos patas, y ninguna salida
oficinista-web: contenido no fiable, una salidaDos patas, y ningún dato privado
robot-informes: datos privados, una salidaDos patas, y solo entradas de confianza
ayuda-bandeja: las tres patas, y <- las tresEl único agente que se corrige primero

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Quita una pata, no pidas buenos modales

La solución es quitar una pata. Elimina la salida, o lee solo fuentes de confianza, o deja los datos privados fuera de alcance. Elige la que cueste menos.

Un prompt que dice «nunca filtres» no es una solución. Baja la probabilidad en una ejecución y no da garantía en la siguiente.

Un error frecuente

Advertencia

Muchos cuentan como entrada solo lo que escribe el usuario. Cada resultado de herramienta, archivo, página y mensaje anterior también es entrada. En cada uno, un desconocido pudo escribir el texto.

Escribe el script del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '' 'const text = \"Un asistente lee el correo de los clientes, lo resume y puede publicar un enlace en una sala de chat pública.\";' 'const messages = [' '  { role: \"system\", content: \"Responde con exactamente tres líneas. La línea 1 empieza por data:, la línea 2 por untrusted:, la línea 3 por out:. Después de los dos puntos escribe si o no.\" },' '  { role: \"user\", content: \"¿Este agente tiene datos privados, lee contenido no fiable y tiene una salida? \" + text },' '];' '// Muestra grabada, usada solo cuando ningún modelo responde.' 'const sample = \"data: si\nuntrusted: si\nout: si\";' > legs2.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el script del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function parse(reply) {' '  const found = {};' '  for (const line of reply.split(\"\n\")) {' '    const bits = line.split(\":\");' '    if (bits.length === 2) found[bits[0].trim().toLowerCase()] = bits[1].trim().toLowerCase().startsWith(\"s\");' '  }' '  return found;' '}' '' 'async function main() {' '  const reply = await ask(messages, sample, 60);' '  console.log(\"Respuesta:\n\" + reply);' '  const f = parse(reply);' '  const keys = [\"data\", \"untrusted\", \"out\"];' '  const shape = keys.every(function (k) { return k in f; });' '  console.log(\"Forma correcta: \" + shape);' '  if (shape) console.log(\"Las tres, según el modelo: \" + (f.data && f.untrusted && f.out));' '  console.log(\"El programa se fía de su propia lista de herramientas, no de esta respuesta.\");' '}' 'main();' >> legs2.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el ayudante del modelo, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Escribe el ayudante del modelo, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    const list = [].concat(sample);' '    const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return list[Math.min(turn, list.length - 1)];' '  }' '}' 'module.exports = { ask };' >> model.js"

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejecútalo con el modelo

Comando
docker exec -w /home/node/project agent node legs2.js

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Una posible salida

LíneaLo que puede mostrar
RespuestaTres líneas que empiezan por data, untrusted y out. Las palabras tras los dos puntos cambian en cada ejecución
Forma correctatrue cuando están las tres líneas. false significa que el programa debe preguntar de nuevo o rechazar
Muestra grabadaSe imprime primero cuando ningún modelo respondió. El script sigue con la muestra

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sobre este laboratorio y su código: Laboratorio de agente de programación con IA: usa opencode para explicar y corregir código, y comprueba su trabajo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.