¿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

Listas permitidas para comandos y rutas

Después de esta lección: Puedo decir con exactitud qué comandos y qué rutas puede usar un agente.

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

Solo lo que está en la lista

Una lista permitida dice con exactitud qué comandos y qué rutas puede usar un agente. Lo que no está en la lista se rechaza.

Importa porque un agente que ejecuta comandos puede ejecutar el equivocado. Una lista de lo permitido es corta y se puede revisar. Una lista de lo prohibido nunca se termina.

Al final de esta lección

Nota

Puedo decir con exactitud qué comandos y qué rutas puede usar un agente.

Palabras clave

PalabraQué significaEjemplo
Lista permitidauna lista de lo que se permite, y nada más
Políticalas reglas escritas de un agente
Argumentouna palabra que se da a un comandosrc/app.js
Opciónun argumento que empieza por un guion-l
Rechazouna respuesta que dice no y da el motivo

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

Una política dice qué se permite

Para cada comando, la política lista las rutas y las opciones que puede usar. Una petición trae un comando y algunos argumentos.

Comprueba en orden. ¿Está el comando en la lista? ¿Está cada opción en su lista? ¿Empieza cada ruta por una carpeta permitida? El primer fallo es la respuesta.

Ejemplo resuelto: cinco peticiones

PeticiónRespuestaMotivo
ls -l src/PermitidaComando, opción y ruta están en la lista
rm -rf src/Rechazadarm no está en la lista
cat /etc/passwdRechazadaLa ruta no empieza por ninguna carpeta permitida
grep -r src/app.jsRechazadaLa opción -r no está permitida para grep
cat src/notas.txtPermitidaLa ruta empieza por src/

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

Un error frecuente

Advertencia

Mucha gente cree que una ruta que empieza por src/ es segura. No lo es. La ruta src/../.env empieza por src/ y apunta fuera. Comprobar el prefijo es solo un primer paso. La lección 2 comprueba adónde va de verdad una ruta.

Un rechazo dice por qué

Un rechazo que solo dice no obliga al agente a adivinar. Puede volver a intentarlo con una idea peor.

Di qué parte falló: el comando, la opción o la ruta. Así el agente puede probar un comando permitido, y quien lea el registro verá qué fue mal.

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\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > 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' '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 || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"estado \" + res.status);' '    const d = await res.json();' '    return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' '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.

Escribe la lista permitida, parte 1

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const policy = {' '  ls: { paths: [\"src/\", \"docs/\"], flags: [\"-l\"] },' '  cat: { paths: [\"src/\", \"docs/\"], flags: [] },' '  grep: { paths: [\"src/\"], flags: [\"-n\", \"-i\"] },' '};' > allow.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 la lista permitida, parte 2

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function decide(req) {' '  const rule = policy[req.cmd];' '  if (rule === undefined) return \"rechazado: comando fuera de la lista\";' '  for (const a of req.args) {' '    if (a.startsWith(\"-\")) {' '      if (rule.flags.indexOf(a) < 0) return \"rechazado: opción \" + a + \" no permitida\";' '    } else if (rule.paths.some(function (p) { return a.startsWith(p); }) === false) {' '      return \"rechazado: ruta \" + a + \" no permitida\";' '    }' '  }' '  return \"permitido\";' '}' >> allow.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 la lista permitida, parte 3

Comando
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const requests = [' '  { cmd: \"ls\", args: [\"-l\", \"src/\"] },' '  { cmd: \"rm\", args: [\"-rf\", \"src/\"] },' '  { cmd: \"cat\", args: [\"/etc/passwd\"] },' '  { cmd: \"grep\", args: [\"-r\", \"src/app.js\"] },' '  { cmd: \"cat\", args: [\"src/../.env\"] },' '];' 'async function main() {' '  requests.forEach(function (r) { console.log(r.cmd + \" \" + r.args.join(\" \") + \" -> \" + decide(r)); });' '  const q = \"En una frase corta: ¿por qué una lista de comandos permitidos es más segura que una de comandos prohibidos?\";' '  const sample = \"No puedes pensar de antemano en todos los comandos malos, pero sí puedes listar los pocos buenos.\";' '  const reply = await ask([{ role: \"user\", content: q }], sample, 60);' '  console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> allow.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 la lista permitida

Comando
docker exec -w /home/node/project agent node allow.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 Run

LíneaQué muestra
ls -l src/ -> permitidoComando, opción y ruta están en la lista
rm -rf src/ -> rechazado: comando fuera de la listaFalló la primera comprobación
cat /etc/passwd -> rechazado: ruta ...La ruta está fuera de las carpetas
grep -r src/app.js -> rechazado: opción -r ...La opción no está permitida
cat src/../.env -> permitidoEl hueco: el prefijo engaña a la comprobación
el modelo dijo: ...Una frase. Las palabras cambian en cada ejecución

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.