Capítulo 3 — Programación I
Mapa de la lección
Lección 03 publicada. Mapa, ejemplo, EX007.
flowchart TD
N0["Resultados de aprendizaje"]
N1["3.1 Por qué la programación importa en seguridad de"]
N2["3.2 Construcciones básicas"]
N3["3.3 Tratar la entrada de forma segura"]
N4["3.4 Pruebas"]
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 Por qué la programación importa en seguridad de"]
N2["3.2 Construcciones básicas"]
N3["3.3 Tratar la entrada de forma segura"]
N4["3.4 Pruebas"]
N5["Síntesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX007"]
[Resultados de aprendizaje]
|
v
[3.1 Por qué la programación importa en seguridad de]
|
v
[3.2 Construcciones básicas]
|
v
[3.3 Tratar la entrada de forma segura]
|
v
[3.4 Pruebas]
|
v
[Síntesis]
|
v
[Ejemplo resuelto] --> [Ejercicio EX007]
Resultados de aprendizaje
Usted podrá (1) escribir programas sencillos en Python con variables, condiciones, bucles, funciones y listas; (2) leer los laboratorios de este libro; (3) tratar la entrada de forma segura; y (4) probar funciones pequeñas.
3.1 Por qué la programación importa en seguridad de la IA
El trabajo de seguridad necesita evidencia, y la evidencia sale de ejecutar cosas: evaluar un modelo con un conjunto de prueba, analizar registros, comprobar archivos. Incluso los programas cortos le hacen más rápido y más preciso. Los laboratorios de este libro usan solo la biblioteca estándar de Python, así que funcionan en cualquier ordenador. El primer script útil de Rina midió con qué frecuencia las respuestas de prueba de Ask Lumen citaban un documento de la clínica, una comprobación que a mano habría llevado horas. Escribirlo también la obligó a definir qué contaba como cita, una pregunta más precisa que aquella con la que había empezado. Los laboratorios con la biblioteca estándar evitan problemas de dependencias, así que un compañero puede volver a ejecutar su trabajo y obtener los mismos números.
3.2 Construcciones básicas
Las variables guardan valores; if elige; for repite; las funciones empaquetan pasos; las listas y los diccionarios guardan colecciones. Lea el laboratorio de evasión que sigue: crea datos sintéticos, entrena con un bucle un modelo diminuto de regresión logística y después mide la exactitud a medida que crece una perturbación. Todavía no necesita entender cada línea; céntrese en la estructura: datos, entrenamiento, evaluación, impresión.
"""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
La salida muestra el patrón con claridad: la exactitud es 0,985 sin perturbación y cae a 0,505 cuando eps llega a uno, cerca de adivinar al azar. La semilla aleatoria fija hace que cada ejecución imprima los mismos números.
3.3 Tratar la entrada de forma segura
Los programas que leen archivos, datos de red o salidas de IA deben tratarlos como no confiables. Convierta el texto en números con cuidado, compruebe los rangos y nunca ejecute texto como código. Un error habitual en las aplicaciones con LLM es pasar la salida del modelo a un comando o a una página web sin comprobaciones; el OWASP LLM 2025 lo llama improper output handling (manejo inadecuado de la salida, LLM05). En Ask Lumen, la reserva que sugiere el modelo es una entrada como cualquier otra: debe analizarse como datos, comprobarse contra reglas y solo entonces pasarse al sistema de citas. El ejemplo resuelto de este capítulo hace exactamente eso con tres comprobaciones del código de clínica, la fecha y el identificador del paciente.
3.4 Pruebas
Escriba pruebas pequeñas con assert: assert classify(0.9) == "high". Pruebe los casos límite: entrada vacía, valores extremos, tipos incorrectos. Las pruebas hacen que sea seguro cambiar el código más adelante. En la comprobación de reservas de Rina, los casos límite incluyen una fecha exactamente a 90 días, una fecha pasada, un código de clínica desconocido, un identificador de paciente ausente y una petición con el identificador de otro paciente. Cada caso recibe una prueba con el resultado esperado escrito al lado. Cuando más tarde cambia la regla de fechas, las pruebas existentes muestran de inmediato si algo más se ha roto.
3.5 Ejemplo resuelto (caso sintético de LCH)
Rina escribió una función que comprueba una petición de reserva producida por Ask Lumen antes de que llegue al sistema de citas: el código de clínica debe ser uno de cinco códigos conocidos, la fecha debe estar dentro de 90 días y el identificador del paciente debe coincidir con el usuario que ha iniciado sesión. Sus pruebas incluían una petición con el identificador de otro paciente, que la función rechazó. Comprobar en código, fuera del modelo, significa que la regla se cumple aunque una instrucción persuada al modelo de pedir la reserva de otro paciente.
3.6 Errores y límites
- Copiar código sin entender lo que hace.
- Confiar en la salida de la IA como si fuera código propio.
- Probar solo el caso normal.
El código copiado puede incluir comportamientos que quien lo copió nunca advirtió, como una llamada insegura que ejecuta texto como comando. Confiar en la salida de la IA como si fuera código propio repite ese error con un autor menos cuidadoso. Probar solo el caso normal deja sin probar justamente las vías que usa un atacante; la prueba de Rina con el identificador de otro paciente es del tipo que detecta problemas reales.
Ejercicios
- EX007 — Estructura del laboratorio. Identifique las partes de datos, entrenamiento, evaluación y salida del laboratorio de evasión. Rúbrica: 3 = las cuatro localizadas correctamente; 2 = tres; 1 = una o dos; 0 = nada.
- EX008 — Lectura del laboratorio. ¿Qué exactitud informa el laboratorio con eps 0.00 y 0.50? Rúbrica: 3 = 0,985 y 0,840; 2 = una; 1 = aproximada; 0 = incorrecta.
- EX009 — Validación. Enumere las tres comprobaciones de la función de reservas de Rina y una más que podría añadir. Rúbrica: 3 = código de clínica, ventana de fechas, coincidencia del paciente + extra razonable (formato de franja horaria, límite de frecuencia); 2 = solo las tres; 1 = una o dos; 0 = nada.
Síntesis
La programación convierte las ideas de seguridad en evidencia. Lea los laboratorios buscando la estructura, trate toda entrada externa —incluida la salida de la IA— como no confiable y pruebe los límites.
Siga estudiando — capítulo 03 de 40
← Capítulo 02 (borrador) · Índice de capítulos del curso · Capítulo 04 (borrador) →