◇ OpenCyber Academy
Tecnólogo · Capítulo 3 · Español

Capítulo 3 — Fundamentos de programación

Aprendizaje gratuito y abierto para quienes desean proteger a las personas y la tecnología. No se necesita una cuenta para estudiar ni consultar las respuestas.

Capítulo 3 — Fundamentos de programación

Mapa de la lección

Lección 03 publicada. Mapa, ejemplo, EX007.

flowchart TD
  N0["Resultados de aprendizaje"]
  N1["3.1 Programas alrededor de los modelos"]
  N2["3.2 La salida del modelo no es confiable"]
  N3["3.3 Validar la salida estructurada"]
  N4["3.5 Lectura del laboratorio"]
  N5["Síntesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5
  N5 --> EX["Ejemplo resuelto"]
  EX --> Q["Ejercicio EX007"]

Dibujo lógico

flowchart LR
  N0["Resultados de aprendizaje"]
  N1["3.1 Programas alrededor de los modelos"]
  N2["3.2 La salida del modelo no es confiable"]
  N3["3.3 Validar la salida estructurada"]
  N4["3.5 Lectura del laboratorio"]
  N5["Síntesis"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX007"]
[Resultados de aprendizaje]
    |
    v
[3.1 Programas alrededor de los modelos]
    |
    v
[3.2 La salida del modelo no es confiable]
    |
    v
[3.3 Validar la salida estructurada]
    |
    v
[3.5 Lectura del laboratorio]
    |
    v
[Síntesis]
    |
    v
[Ejemplo resuelto] --> [Ejercicio EX007]

Resultados de aprendizaje

Usted podrá (1) escribir Python sencillo para llamar a servicios de IA y probarlos de forma segura; (2) validar la entrada no confiable y la salida del modelo; (3) tratar correctamente los errores y los secretos; y (4) explicar por qué la salida del modelo debe tratarse como datos no confiables.

3.1 Programas alrededor de los modelos

La mayor parte del trabajo de seguridad de la IA es programación corriente: construir prompts, analizar respuestas, llamar a herramientas, escribir pruebas. La biblioteca estándar de Python basta para muchas tareas: json para analizar salidas estructuradas, re para patrones, hashlib para comprobaciones de integridad, unittest para pruebas. El trabajo de Jonas en Ask Brightwell es sobre todo de este tipo: escapar la salida en la consola del personal, validar el JSON de la herramienta de devoluciones y escribir pruebas que fallan cuando una consulta entre usuarios distintos tiene éxito. Nada de ello exige cambiar el modelo. Cada cosa es Python sencillo que un revisor puede leer en minutos y contrastar con la amenaza que aborda.

3.2 La salida del modelo no es confiable

La respuesta de un modelo puede contener texto que un atacante plantó mediante un documento. Si el código inserta ese texto en HTML, SQL o un comando de shell sin escaparlo, el atacante obtiene una inyección en esos sistemas: OWASP LLM05 Improper Output Handling (tratamiento inadecuado de las salidas). Trate la salida exactamente como la entrada del usuario: escápela para HTML, use consultas parametrizadas y nunca la pase a un shell. La reseña plantada por Jonas en la consola del personal lo mostró directamente: el asistente citó una etiqueta de imagen de una reseña y la consola la representó, con lo que el script se ejecutó en el navegador de un empleado. La solución fue escapar, no un modelo mejor.

3.3 Validar la salida estructurada

Cuando un modelo debe devolver una acción, pida JSON y valídelo de forma estricta: analícelo, compruebe que solo existen las claves esperadas, compruebe los tipos, compruebe los valores permitidos (por ejemplo, action en {"lookup", "return"}) y rechace todo lo demás. Nunca «arregle» una salida no válida adivinando. En Ask Brightwell, el orquestador solo acepta lookup y return como acciones y comprueba que el número de pedido sea una cadena de dígitos. Cualquier otra cosa, incluidas las claves adicionales que invente el modelo, hace que la petición se rechace y se registre, de modo que una propuesta mal formada nunca llega a la herramienta de devoluciones. Después, el servicio de políticas hace su propia comprobación sobre la acción validada.

3.4 Errores y secretos

Falle de forma cerrada: si la validación falla o una herramienta da error, no ejecute la acción. Guarde las claves de API en variables de entorno o en un gestor de secretos, nunca en el código ni en los registros.

"""Lab E: evasion of a toy linear classifier (synthetic data, stdlib only).
Trains logistic regression on two synthetic clusters, then applies a
fast-gradient-sign (FGSM-style) perturbation of size eps to every test point
and reports clean vs adversarial accuracy. Teaching model only."""
import math, random
rng = random.Random(7)
def point(label):
    cx = 1.0 if label else -1.0
    return [rng.gauss(cx, 0.7), rng.gauss(cx, 0.7)], label
train = [point(i % 2) for i in range(400)]
test = [point(i % 2) for i in range(200)]
w, b = [0.0, 0.0], 0.0
sig = lambda z: 1 / (1 + math.exp(-z))
for epoch in range(200):
    gw, gb = [0.0, 0.0], 0.0
    for x, y in train:
        p = sig(w[0]*x[0] + w[1]*x[1] + b)
        gw[0] += (p - y)*x[0]; gw[1] += (p - y)*x[1]; gb += p - y
    w = [w[i] - 0.1*gw[i]/len(train) for i in range(2)]; b -= 0.1*gb/len(train)
def acc(data, eps):
    ok = 0
    for x, y in data:
        # gradient of the loss w.r.t. x is (p - y) * w; FGSM steps along its sign
        p = sig(w[0]*x[0] + w[1]*x[1] + b)
        xa = [x[i] + eps*math.copysign(1, (p - y)*w[i]) for i in range(2)]
        ok += (sig(w[0]*xa[0] + w[1]*xa[1] + b) >= 0.5) == bool(y)
    return ok / len(data)
print(f"weights w=({w[0]:.3f}, {w[1]:.3f}) b={b:.3f}")
for eps in (0.0, 0.25, 0.5, 0.75, 1.0):
    print(f"eps={eps:.2f} accuracy={acc(test, eps):.3f}")

Salida esperada:

weights w=(1.795, 1.756) b=-0.080
eps=0.00 accuracy=0.985
eps=0.25 accuracy=0.950
eps=0.50 accuracy=0.840
eps=0.75 accuracy=0.660
eps=1.00 accuracy=0.505

En Ask Brightwell, si la herramienta de pedidos agota el tiempo de espera, el asistente le dice al cliente que ahora no puede consultar el pedido, en lugar de adivinar. La clave de API del proveedor reside en el gestor de secretos, y el filtro de registros del orquestador la elimina de cualquier mensaje de error antes de escribirlo. Jonas añadió una prueba que falla si aparece en una línea de registro una cadena con forma de clave, de modo que la regla se comprueba en cada compilación.

3.5 Lectura del laboratorio

El laboratorio entrena un pequeño clasificador lineal y muestra cómo cae su exactitud a medida que las entradas se desplazan eps en la peor dirección: 0,985 sin perturbación y 0,505 con eps 1,0. Recuerda que la decisión de un modelo puede dirigirse con cambios pequeños y deliberados en la entrada; el código que rodea a los modelos no debe suponer que sus salidas son correctas. Para Brightwell, el laboratorio respalda una decisión de diseño, no un hecho sobre ReturnGuard: las decisiones que importan no deben descansar en una sola puntuación sin comprobaciones. En el laboratorio, las perturbaciones las elige el atacante; los atacantes reales tienen límites sobre lo que pueden cambiar, y por eso el laboratorio es un recordatorio, no una medición.

3.6 Ejemplo resuelto (caso sintético de Brightwell)

La consola del personal de Ask Brightwell mostraba las respuestas del modelo como HTML sin procesar. Jonas planta en una copia de prueba una reseña de producto que contiene <img src=x onerror=...>; el asistente la cita y el script se ejecuta en el navegador del personal. Cambia la consola para que escape la salida y añade una prueba unitaria. La corrección está donde los datos salen del sistema, en la consola, así que se mantiene diga lo que diga el modelo. La prueba unitaria planta la misma etiqueta de imagen y falla si la consola vuelve a representarla como HTML, lo que protege frente a un cambio posterior que reintroduzca el fallo.

3.7 Errores y límites

Cada uno convierte el texto de un modelo en una acción en otro sistema. La consola de Ask Brightwell mostró el primero; la validación estricta del JSON de la herramienta de devoluciones evita el segundo; y guardar la clave del proveedor en el gestor de secretos evita el tercero. Tener pruebas para cada uno significa que un cambio posterior no puede reintroducir sin ruido la debilidad, que es precisamente la razón de escribirlas como código.

Ejercicios

Síntesis

Programar alrededor de los modelos significa validar y codificar todo lo que pasa a otros sistemas —en especial la salida del modelo— y fallar de forma cerrada.

Siga estudiando — capítulo 03 de 30

← Capítulo 02 (borrador) · Índice de capítulos del curso · Capítulo 04 (borrador) →