Módulo 7 de 14

Módulo 7: Cadena de suministro de modelos y datos

Módulo 7: Cadena de suministro de modelos y datos

Cada aplicación de este curso, hasta ahora, ha dado el modelo por hecho: una pieza que ya está ahí, con la que el orquestador conversa. Este módulo entra justo en esa pieza y la trata como lo que es, una dependencia de software que alguien descargó de algún sitio, publicada por alguien que la mayoría de equipos nunca ha verificado, entrenada con datos que casi nadie puede enumerar. El módulo 2 de este curso ya presentó los identificadores LLM03:2025 (cadena de suministro) y LLM04 (envenenamiento de datos y modelo) del Top 10 de OWASP con dos o tres frases cada uno; aquí se desarrollan enteros, con el mismo nivel de detalle con el que este curso trató la inyección de prompt o la agencia excesiva.

La cadena empieza antes de escribir una sola línea de código y no termina cuando el modelo entra en producción. Vas a ver por qué el formato en el que se distribuyen los pesos de un modelo no es un detalle técnico sino una superficie de ejecución de código, qué se puede firmar y verificar de verdad hoy, en qué fase concreta se envenena un modelo y quién tiene margen real para evitarlo, y qué hace falta para que una organización sepa, en cualquier momento, qué modelo exacto está sirviendo cada aplicación suya.

Qué aprenderás

  • Qué significa tratar un modelo como una dependencia de software: origen, publicador, licencia y datos de entrenamiento, y por qué la mayoría de esas preguntas no tienen respuesta verificable hoy.
  • La diferencia real entre pesos abiertos y modelo de código abierto, con la definición de código abierto de IA de la Open Source Initiative y dos modelos que caen a cada lado de esa línea.
  • Por qué cargar un punto de control en formato pickle puede ejecutar código arbitrario, qué formato se diseñó para evitarlo y qué garantiza exactamente ese formato seguro, y qué no garantiza.
  • Cómo se firma y se verifica la procedencia de un modelo hoy, y qué aporta una lista de materiales de IA frente a un simple archivo de licencia.
  • En qué fase puede envenenarse un modelo (preentrenamiento, ajuste fino, corpus de recuperación) y qué control cabe de verdad en cada una según quién la controla.
  • Qué se sabe públicamente de las puertas traseras en modelos: cómo funcionan, por qué pueden sobrevivir al ajuste fino, y qué identificadores les da la taxonomía de NIST y MITRE ATLAS.
  • Por qué cada biblioteca de orquestación, extensión o servidor de herramientas que importa tu aplicación es parte de esta misma cadena de suministro, con casos reales de dependencias comprometidas.
  • Cómo se construye el registro de modelos de una organización: inventario, aprobación, versión en producción y retirada, con las subcategorías concretas del marco de gestión de riesgo de IA de NIST.
  • A documentar la procedencia completa de un modelo abierto real, señalando con precisión qué partes de esa procedencia no se pueden verificar.

El modelo como dependencia de software

Cuando un equipo instala una biblioteca de Python, alguien (una auditoría interna, un escáner de dependencias, la simple costumbre) espera poder responder a un puñado de preguntas: quién la publicó, bajo qué licencia, qué versión exacta es, y qué cambió desde la anterior. Un modelo de lenguaje descargado de un repositorio público es la misma clase de dependencia, con el mismo peso dentro de la aplicación final, y aun así casi nunca se le hacen esas preguntas con el mismo cuidado.

Prueba a responderlas para un modelo concreto que tengas descargado. ¿Quién lo entrenó, la organización que firma la publicación o un tercero que subió una copia con el mismo nombre? ¿Qué licencia lleva de verdad, la que anuncia la página del repositorio o la que hay escrita en el archivo de licencia del propio paquete, que a veces no coincide? ¿Qué datos vio durante el entrenamiento, con qué filtrado, con qué fecha de corte? Para la inmensa mayoría de modelos que se pueden descargar hoy, la respuesta a la tercera pregunta es que no se puede saber con precisión, y ni siquiera el propio publicador la documenta siempre completa.

La práctica de acompañar un modelo con una tarjeta de modelo no es nueva: la propuso un equipo de investigación en el artículo «Model Cards for Model Reporting», presentado en la conferencia ACM sobre equidad, responsabilidad y transparencia de 2019 (FAT* 2019), con un documento breve que cubre el uso previsto del modelo, sus límites conocidos y los datos con los que se entrenó. Años después, la mayoría de modelos publicados en repositorios abiertos traen algo llamado tarjeta de modelo, pero el contenido real varía muchísimo entre unos y otros: algunos listan el conjunto de datos exacto con su licencia, y otros se quedan en una frase genérica sobre datos disponibles públicamente en internet, que no permite verificar nada en concreto.

Pesos abiertos y código abierto no son lo mismo

La confusión más extendida en esta cadena de suministro es tratar «modelo abierto» como una única categoría. No lo es. La Open Source Initiative, la organización que mantiene la definición de código abierto para software desde su fundación en 1998, publicó el 28 de octubre de 2024 la versión 1.0 de su Open Source AI Definition, con cuatro libertades que tienen que cumplirse a la vez para que un sistema de IA merezca esa etiqueta: usarlo con cualquier fin sin pedir permiso adicional, estudiar cómo funciona, modificarlo, y compartirlo con o sin cambios. Publicar solo los pesos entrenados de un modelo no cumple ninguna de las cuatro por completo: permite usarlo y, hasta cierto punto, modificarlo, pero no permite estudiar cómo se construyó de verdad ni reproducirlo, porque falta el código de entrenamiento y, casi siempre, los datos.

La propia OSI lo resume en un documento dedicado a esta distinción: un modelo con pesos abiertos no ofrece el proceso de entrenamiento subyacente, el código, ni los detalles de los datos que hacen falta para el uso, estudio, modificación y difusión completos que exige su definición. Dos modelos reales muestran los dos extremos de la misma etiqueta «abierto». OLMo, del instituto Ai2, publica los pesos, el código de entrenamiento, los registros de entrenamiento y el propio conjunto de datos de preentrenamiento (llamado Dolma), todo bajo licencia Apache 2.0: es de los pocos modelos de uso extendido que hoy cumpliría de verdad la definición de la OSI. Llama, de Meta, publica solo los pesos bajo una licencia propia que la propia OSI señaló en febrero de 2025 como incompatible con su definición en tres puntos concretos (no cumple la libertad de uso con cualquier fin, discrimina entre tipos de usuario, y restringe el campo de aplicación). Con la terminología correcta, Llama es un modelo de pesos abiertos, no un modelo de código abierto, aunque buena parte de la documentación técnica del sector lo siga llamando así sin distinguir.

El formato importa: por qué cargar un modelo puede ejecutar código

De todas las preguntas que un equipo puede hacerse sobre un modelo, hay una con una respuesta técnica precisa y verificable, no una cuestión de confianza: en qué formato de archivo llegan los pesos, porque de ese formato depende si cargarlos puede ejecutar código en el proceso que los carga.

Pickle: por qué deserializar no es lo mismo que leer datos

El formato por defecto para guardar y cargar un modelo de PyTorch usa el módulo pickle de la biblioteca estándar de Python, y la propia documentación de Hugging Face sobre este riesgo lo explica con una frase que conviene leer dos veces: pickle no es simplemente un protocolo de serialización, da a quien lo usa la capacidad de ejecutar código Python en el momento de deserializar. Un archivo pickle no guarda solo números: guarda una secuencia de instrucciones que un intérprete ejecuta una a una al cargarlo, y dos de esas instrucciones, GLOBAL y REDUCE, sirven exactamente para eso. La primera le dice al proceso que importe una función o una clase concreta; la segunda le dice que la llame con los argumentos que vienen a continuación en el propio archivo. Cargar un modelo en formato pickle no es leer un archivo de datos, es ejecutar un programa que otra persona escribió, con el mismo nivel de confianza que le darías a un script descargado de un sitio desconocido y lanzado sin mirarlo.

Esto no es un riesgo teórico. Trail of Bits publicó ya en 2021 fickling, una herramienta pensada para analizar y fabricar pickles maliciosos con el objetivo declarado de que el sector tomara en serio el problema, y desde entonces se han documentado casos reales sobre modelos alojados en repositorios públicos. ReversingLabs publicó el 6 de febrero de 2025 el hallazgo de dos modelos en Hugging Face, con la técnica bautizada nullifAI, que escondían una puerta trasera de tipo shell inversa dentro de un pickle comprimido con el formato 7z en vez del ZIP habitual, precisamente para que el escáner de importaciones de la plataforma no llegara a analizarlos, aunque la propia función de carga de PyTorch sí los ejecutara igualmente al toparse con el código malicioso antes de que el archivo corrupto provocara un error. Hugging Face retiró los dos modelos en menos de 24 horas tras recibir el aviso, pero el hallazgo confirma algo que su propia documentación ya admite: el escáner de pickles del Hub funciona con una lista de permitidos mantenida «de la mejor manera posible», no con una garantía. PyTorch expone hoy el parámetro weights_only en su función de carga precisamente para mitigar esto, restringiendo qué tipos de objeto puede reconstruir el deserializador; ayuda, pero no convierte pickle en un formato seguro por diseño, solo reduce lo que puede pasar si algo sale mal.

Safetensors: qué garantiza el formato pensado para esto

Safetensors es el formato que Hugging Face diseñó explícitamente para sustituir a pickle en la distribución de pesos, y su propio repositorio lo dice sin rodeos: la pregunta que responde el formato es si se puede usar un archivo descargado al azar sin esperar que ejecute código arbitrario, y en su tabla comparativa con otros formatos marca esa propiedad, llamada «Safe», como cumplida para safetensors y como incumplida para pickle, con la nota «Unsafe, runs arbitrary code» en la fila que le corresponde a este último. Lo consigue por diseño, no por análisis: un archivo safetensors no contiene ninguna instrucción ejecutable, solo tres partes en secuencia, ocho bytes con la longitud de una cabecera, la propia cabecera en JSON con el nombre, el tipo de dato, la forma y el desplazamiento de bytes de cada tensor, y el bloque de datos binarios de los tensores. No hay ningún paso de deserialización de objetos Python de por medio: cargar un archivo safetensors es leer números en las posiciones que la cabecera indica, nada más.

{
  "embedding": {"dtype": "F32", "shape": [2, 2], "data_offsets": [0, 16]},
  "attention": {"dtype": "F32", "shape": [2, 3], "data_offsets": [16, 40]}
}

El formato también se protege frente a un fallo de otro tipo: la propia especificación limita la cabecera a un máximo de 100 MB, para evitar que un archivo fabricado obligue a analizar un JSON descomunal solo para leer el primer tensor, y exige que los desplazamientos de bytes de cada tensor no se solapen entre sí y queden dentro del tamaño real del archivo. Un lector correcto no necesita reservar memoria de más ni leer fuera de los límites del archivo para procesar una cabecera manipulada.

Lo que safetensors no garantiza, y conviene decirlo con la misma claridad, es el contenido de los números que hay dentro. El formato resuelve por completo el problema de la ejecución de código: no hay forma de que cargar un archivo safetensors, por manipulado que esté su contenido, ejecute nada que no sea leer bytes. No resuelve si esos pesos concretos codifican un comportamiento que alguien introdujo a propósito durante el entrenamiento, la puerta trasera de la que trata más adelante este mismo módulo. Un modelo con una puerta trasera entrenada, distribuido en formato safetensors, es tan seguro de cargar, en el sentido estricto de «no ejecuta código», como el mismo modelo sin ninguna puerta trasera: el formato garantiza cómo se cargan los bytes, no qué significan.

from safetensors import safe_open

pesos = {}
with safe_open("modelo.safetensors", framework="pt", device="cpu") as f:
    for nombre in f.keys():
        pesos[nombre] = f.get_tensor(nombre)

La recomendación práctica que se deriva de todo esto no es complicada: si un modelo existe en las dos versiones, cargar siempre la safetensors, y si solo existe en pickle, tratarlo con la misma cautela que cualquier ejecutable sin firmar, sea cual sea la reputación del repositorio de origen.

Verificación de procedencia: firma, hash y lista de materiales

Saber que un archivo no puede ejecutar código al cargarlo no dice nada sobre si es el archivo que su publicador subió de verdad, o una copia alterada en tránsito, en un espejo no oficial, o en el propio repositorio tras una cuenta comprometida. El Top 10 de OWASP para aplicaciones de LLM lo llama procedencia débil en su entrada LLM03:2025 y lo describe sin rodeos: hoy no hay garantías fuertes de procedencia en los modelos publicados, y un atacante que compromete la cuenta de un proveedor en un repositorio de modelos puede sustituir el archivo sin que nada lo impida técnicamente.

Firmar el artefacto, no solo el repositorio

Firmar commits de Git, algo que ya hacen muchos equipos, certifica quién subió un cambio a un repositorio; no certifica que el archivo binario del modelo, generado fuera de ese repositorio y de varios gigabytes, sea el mismo que se firmó. Para eso existe un proyecto más reciente, OpenSSF Model Signing, impulsado por la Open Source Security Foundation junto con el proyecto Sigstore, con una versión 1.0 publicada en abril de 2025. La herramienta de referencia se llama model-signing y funciona con el mismo modelo de confianza que Sigstore ya popularizó para firmar paquetes de software: sin claves de largo plazo que alguien tiene que custodiar, con un flujo de identidad OIDC que emite un certificado de corta duración en el momento exacto de firmar.

pip install model-signing

model_signing sign modelo.safetensors --signature modelo.sig

Quien recibe después el modelo verifica la firma contra la identidad que espera, no contra una clave criptográfica que ha tenido que intercambiar antes por otro canal:

model_signing verify modelo.safetensors 
  --signature modelo.sig 
  --identity "equipo-modelos@ejemplo.com" 
  --identity-provider "https://accounts.google.com"

NVIDIA firma con esta especificación todos los modelos que publica en su catálogo NGC desde marzo de 2025, y Google ha integrado la verificación en Kaggle: dos señales de que esto ya se usa en producción y no se ha quedado en la propuesta de un repositorio experimental. Nada de esto sustituye a lo anterior: firmar un modelo con una puerta trasera entrenada produce una firma perfectamente válida sobre un archivo perfectamente malicioso. La firma certifica que el archivo es el que el firmante publicó, no que lo que el firmante publicó sea inofensivo.

La lista de materiales de IA: qué existe hoy y qué no

Un SBOM, lista de materiales de software, lleva más de una década siendo la respuesta estándar a «qué componentes lleva de verdad este software», y el sector del aprendizaje automático ha empezado a adaptar la misma idea, con dos propuestas concretas que sí tienen soporte real en una especificación publicada, no solo en un artículo de blog.

CycloneDX, el formato de SBOM del proyecto OWASP, añadió en su versión 1.5 (2023) un tipo de componente llamado machine-learning-model, con un objeto asociado llamado tarjeta de modelo que puede llevar los parámetros del modelo, los conjuntos de datos de referencia, métricas de rendimiento y consideraciones éticas, con esa combinación conocida en conjunto como ML-BOM. Por su parte, SPDX (System Package Data Exchange), el otro formato de SBOM mayoritario, mantenido por la Linux Foundation y publicado como norma ISO/IEC 5962, incorporó en su versión 3.0, del 16 de abril de 2024, un perfil de IA y un perfil de conjunto de datos aparte, con campos propios para el tipo de dataset, su tamaño, su disponibilidad (descarga pública o solo bajo formulario) y su proceso de recogida.

Ninguno de los dos formatos resuelve el problema de fondo: que la organización que entrena un modelo tenga la información completa que un ML-BOM pide y decida publicarla. Un ML-BOM describe con precisión la estructura de lo que el publicador quiera contar; no obliga a que cuente el conjunto de datos de entrenamiento si prefiere no hacerlo. Lo que sí cambia frente a no tener nada es que existe un sitio estándar, verificable por máquina, donde buscar esa información antes de dar por hecho que no existe, y una forma de que un equipo que sí quiere ser transparente lo sea con un formato que otras herramientas ya saben leer. El propio Top 10 de OWASP recoge esta práctica entre sus mitigaciones para LLM03:2025: mantener un inventario actualizado mediante un SBOM firmado y sin manipular, y usar solo modelos de fuentes verificables con comprobaciones de integridad mediante firma y hashes de archivo, precisamente para compensar la falta de una procedencia fuerte en el ecosistema actual.

Campo Qué responde
Publicador y firma Quién lo entrenó o lo redistribuye, y si esa identidad se puede verificar con una firma
Licencia Qué usos permite de verdad, no lo que anuncia el nombre del repositorio
Formato de distribución Si los pesos llegan en un formato que ejecuta código al cargarlos
Hash del artefacto Permite comprobar que el archivo descargado es, bit a bit, el que el publicador anunció
Modelo o modelos ancestros De qué modelo base parte, si es un ajuste fino o una fusión de otros
Datasets de referencia Qué conjuntos de datos declara el publicador, con su propia licencia y procedencia
Fecha de corte y de publicación Hasta cuándo llega el conocimiento del modelo y cuándo se hizo pública esta versión
Limitaciones conocidas Lo que el propio publicador reconoce que el modelo no hace bien o para qué no debería usarse

Envenenamiento de datos y modelo (LLM04): tres fases, tres niveles de control real

La entrada LLM04 del Top 10 de OWASP define el envenenamiento de datos como la manipulación de los datos de preentrenamiento, ajuste fino o de las representaciones vectoriales para introducir vulnerabilidades, puertas traseras o sesgos, y señala tres fases del ciclo de vida donde puede ocurrir: preentrenamiento, ajuste fino, y la recuperación de contexto en tiempo de inferencia. Conviene tratarlas por separado porque el margen de control de un equipo de aplicación cambia por completo de una a otra, y hablar de «envenenamiento» como si fuera un único problema esconde esa diferencia.

Preentrenamiento: casi nada que un equipo de aplicación pueda hacer

Un modelo de fundación moderno se entrena con cantidades de texto que se miden en billones de tokens, recogidos en buena parte rastreando la web abierta; NIST AI 100-2e2025 cita un cálculo de Hoffmann et al. según el cual entrenar de forma óptima en cómputo un modelo de 520 000 millones de parámetros pediría unos 11 billones de tokens de datos. Esa escala es, a la vez, la razón por la que el preentrenamiento funciona y la razón por la que es tan difícil de proteger: nadie audita a mano 11 billones de tokens, así que la superficie donde insertar contenido malicioso es enorme y barata de alcanzar.

Nicholas Carlini y su equipo lo demostraron de forma práctica en 2023, con dos técnicas concretas descritas en su artículo «Poisoning Web-Scale Training Datasets is Practical». La primera, envenenamiento de vista dividida, se apoya en que el contenido de una URL puede cambiar entre el momento en que se anotó como parte de un dataset y el momento en que un descargador real la visita: los autores compraron dominios caducados que aparecían citados en listas de URLs de conjuntos de datos como LAION-400M o COYO-700M y sirvieron en ellos contenido propio, por un coste de unos 60 dólares para envenenar el 0,01 % de esos conjuntos. La segunda, envenenamiento por adelantamiento, se dirige a instantáneas periódicas de datasets que se generan a partir de contenido editable, como Wikipedia: basta con insertar una edición maliciosa justo antes de que se tome la instantánea programada para que quede capturada en el dataset resultante, aunque alguien la revierta minutos después en la propia Wikipedia.

Frente a esto, la defensa que puede aplicar quien entrena el modelo, no quien solo lo usa, incluye verificar con un hash criptográfico que el contenido descargado de cada URL coincide con el que se anotó al construir la lista de fuentes, algo que el propio NIST recomienda en esta misma taxonomía. Un equipo que solo consume un modelo de fundación ya entrenado no tiene forma de aplicar ninguna de estas dos defensas: para cuando el modelo llega a sus manos, el preentrenamiento ya pasó. Lo único que le queda es la pregunta de procedencia de la sección anterior, qué publicador entrena con qué disciplina, y si documenta algo al respecto.

Ajuste fino: aquí sí hay mucho margen

El ajuste fino cambia el reparto de control por completo, porque suele ser un proceso que la propia organización ejecuta, con su propio conjunto de datos, sobre un modelo base ya publicado. Eso significa que las defensas estándar de cualquier canalización de datos (procedencia de cada ejemplo, control de versiones del propio dataset, detección de valores atípicos antes de entrenar, un conjunto de validación aislado que no participó en la selección de ejemplos) se pueden aplicar de verdad, porque el equipo que ajusta el modelo es dueño del proceso completo.

El riesgo, en esta fase, tiene dos caras. Si el ajuste fino usa un dataset propio, el peligro es el mismo que en cualquier canalización con muchas fuentes: alguien introduce ejemplos manipulados entre los legítimos, con la misma lógica de las dos técnicas de Carlini pero a una escala mucho menor y, por eso, mucho más fácil de vigilar. Si en cambio el ajuste fino parte de un adaptador de terceros (un LoRA ya entrenado por otra persona, en vez de datos propios), el riesgo cambia de sitio: el propio Top 10 de OWASP dedica un ejemplo de vulnerabilidad a esto, adaptadores LoRA maliciosos que comprometen la integridad de un modelo base al desplegarse juntos en una plataforma de servido como vLLM, sin que el adaptador en sí pese lo suficiente como para llamar la atención de nadie.

Lo más incómodo de esta fase es que una puerta trasera introducida en el propio preentrenamiento, o en un modelo base malicioso, no siempre desaparece al ajustarlo. Kurita, Michel y Neubig demostraron en 2020, en «Weight Poisoning Attacks on Pre-trained Models», que un ataque de envenenamiento de pesos puede sobrevivir al ajuste fino posterior de un modelo preentrenado, y un equipo de Anthropic, en un trabajo de enero de 2024 titulado «Sleeper Agents», mostró que un comportamiento entrenado a propósito para activarse ante un disparador concreto puede persistir incluso después de aplicar las técnicas de entrenamiento de seguridad más habituales sobre ese modelo. La lectura práctica no es que el ajuste fino no sirva de nada: es que ajustar un modelo base que ya venía comprometido no es una forma fiable de limpiarlo. La higiene tiene que empezar por comprobar la procedencia de ese modelo base antes de invertir en ajustarlo, no después.

Recuperación en tiempo de inferencia: control total, sin excusa

La tercera fase es la que un equipo de aplicación controla al cien por cien, porque el corpus de un sistema de RAG lo decide, lo ingiere y lo mantiene la propia aplicación, no un tercero en otro punto de la cadena. El módulo 5 de este curso ya desarrolló en detalle cómo se envenena un índice de recuperación, con las técnicas concretas que documenta MITRE ATLAS para esta fase, y qué controles de admisión, metadatos e higiene del corpus lo evitan; no hace falta repetirlo aquí. Lo que conviene retener en este módulo es la comparación con las dos fases anteriores: si en el preentrenamiento el margen de control es casi nulo y en el ajuste fino es amplio pero compartido con quien publicó el modelo base, en el corpus de recuperación no hay ninguna excusa razonable para no tener control completo, porque cada documento que entra ahí pasó, en algún momento, por una decisión de alguien de la propia organización.

Puertas traseras en modelos

Una puerta trasera en un modelo de aprendizaje automático es un comportamiento entrenado a propósito para activarse solo ante un patrón concreto (una palabra, una frase, un píxel en una imagen) mientras el modelo se comporta con normalidad ante cualquier otra entrada, lo que la hace casi invisible en una evaluación estándar de rendimiento. NIST AI 100-2e2025, la taxonomía de aprendizaje automático adversario que el módulo 2 de este curso ya presentó, la trata como un subtipo con nombre propio dentro de los ataques de envenenamiento, con identificador NISTAML.023 («Backdoor Poisoning»), y la separa con precisión del envenenamiento dirigido (NISTAML.024): el primero busca que cualquier entrada con el patrón activador se clasifique como decida el atacante; el segundo busca que un conjunto concreto de entradas, ya conocido de antemano, se clasifique mal, sin necesitar ningún patrón añadido en tiempo de inferencia.

El propio documento de NIST cita el origen académico del término: Gu, Dolan-Gavitt y Garg lo formalizaron en 2017 con BadNets, el primer ataque de envenenamiento por puerta trasera documentado, sobre clasificadores de imágenes. Añadieron un parche pequeño y reconocible a un subconjunto de imágenes de entrenamiento y cambiaron su etiqueta a la clase que el atacante quería, de modo que el clasificador aprendía a asociar ese parche con esa clase sin que el rendimiento general del modelo se resintiera de forma visible. Desde entonces, la literatura académica que cita NIST ha llevado la misma idea a modelos de audio, de lenguaje y de clasificación de malware, con disparadores cada vez más difíciles de detectar a simple vista: ocultos con técnicas de esteganografía, integrados como objetos físicos delante de una cámara, o repartidos por toda la entrada en vez de en un único parche.

Trasladado a un modelo de lenguaje, NIST señala en su sección sobre IA generativa que el mismo mecanismo puede insertar, mediante envenenamiento de datos, una palabra o frase que actúe como jailbreak universal en cuanto aparece en la conversación, o que altere el comportamiento del modelo solo ante consultas de un tipo concreto, como hacer que un modelo de sugerencia de código proponga código con vulnerabilidades de forma sistemática ante un patrón de petición determinado. MITRE ATLAS documenta el mismo comportamiento con sus propios identificadores: AML.T0018.000 («Poison AI Model») para manipular los pesos de un modelo con este fin, y AML.T0043.004 («Insert Backdoor Trigger») para el paso de añadir el patrón activador a los datos de entrada en el momento del ataque.

Sobre lo que hace falta decir con honestidad: esto sigue siendo, sobre todo, un problema de investigación abierto. NIST dedica más espacio a la mitigación de puertas traseras que a cualquier otro tipo de envenenamiento (saneamiento de datos de entrenamiento, reconstrucción del disparador, inspección del propio modelo entrenado en busca de indicios) y reconoce, a la vez, que cada clase de defensa tiene un punto débil documentado frente a un atacante que la conozca de antemano. Ninguna combinación de estas técnicas se ofrece hoy como una solución cerrada, y este módulo no va a fingir que existe una. Lo que sí hay, y es lo que puede aplicar de verdad un equipo que no investiga defensas contra puertas traseras a tiempo completo, es la misma cadena de controles del resto de este módulo: procedencia verificada del modelo base, formato seguro de distribución, y trazabilidad de qué modelo exacto está en producción para poder retirarlo si aparece evidencia de que estaba comprometido.

Dependencias del ecosistema: cada biblioteca es código que se ejecuta

El modelo es la pieza más comentada de esta cadena de suministro, pero no la única que corre dentro de una aplicación de IA. El orquestador que presentó el módulo 1 de este curso suele apoyarse en un framework como LangChain o LlamaIndex; el bucle de un agente, en el que el módulo 6 entró en detalle, puede depender de un servidor de herramientas del protocolo de contexto para modelos escrito por un tercero; y cualquiera de las dos cosas puede tirar de una plantilla de prompt publicada en un repositorio público en vez de escrita a mano por el propio equipo. Cada una de esas piezas es una dependencia de software convencional, con la misma superficie de riesgo que cualquier paquete que un equipo importa sin revisar, y con una diferencia agravante: muchas de ellas se ejecutan con el mismo nivel de confianza que el propio orquestador, no en un entorno aislado aparte.

El caso de Ray, el framework de cómputo distribuido que varios proyectos de IA usan para repartir el entrenamiento o la inferencia entre máquinas, es un ejemplo documentado de lo que pasa cuando esto sale mal. En marzo de 2024, investigadores de seguridad reportaron que miles de servidores con clústeres de Ray expuestos a internet llevaban hasta siete meses comprometidos, explotando que el panel de control y la API de cliente de Ray no exigen autenticación por diseño (identificado como CVE-2023-48022, aunque el propio mantenedor del proyecto discute que sea una vulnerabilidad y lo describe como una decisión de diseño intencionada), combinado con la costumbre extendida de exponer esos clústeres a internet pese a que la propia documentación del proyecto lo desaconseja. Los atacantes consiguieron ejecución remota de comandos, con acceso a credenciales guardadas en el historial y capacidad de robar modelos y conjuntos de datos propios.

MITRE ATLAS le da a esto un identificador propio dentro de su técnica de compromiso de la cadena de suministro de IA: AML.T0010.001 («AI Software») cubre justo los paquetes de software que una aplicación de IA importa sin verificar, y AML.T0010.005 («AI Agent Tool») cubre el caso más nuevo, un servidor de herramientas de agente comprometido o directamente malicioso. Hay incluso una técnica pensada para el patrón exacto que hace tan difícil confiar en un ecosistema que cambia rápido, AML.T0109 («AI Supply Chain Rug Pull»): un componente legítimo, con buena reputación y adopción real, que un día publica una actualización con una variante maliciosa, contando con que la revisión más estricta suele ocurrir solo la primera vez que un equipo adopta una dependencia, no en cada actualización posterior. Quien quiera un ejemplo de este mismo patrón fuera del mundo de la IA no tiene que buscar mucho: la puerta trasera descubierta en marzo de 2024 en xz-utils, una biblioteca de compresión que llevaba años en prácticamente todas las distribuciones de Linux, se introdujo así, con un colaborador que ganó la confianza del proyecto durante meses antes de insertar el código malicioso en una actualización de rutina.

La defensa contra todo esto no es distinta de la que ya exige cualquier canalización de desarrollo seguro: fijar la versión exacta de cada dependencia en vez de apuntar siempre a la última, revisar el registro de cambios antes de actualizar en vez de hacerlo de forma automática, y aplicar a los componentes de IA los mismos controles de vulnerabilidades conocidas y componentes desactualizados que ya exige cualquier programa serio de seguridad de aplicaciones. El módulo 2 de este curso ya presentó NIST SP 800-218A como la extensión del marco de desarrollo seguro de software a los modelos generativos; esa misma disciplina, aplicada sin excepciones a cada biblioteca de orquestación, cada extensión y cada servidor de herramientas, es la que corta este eslabón antes de que se convierta en un incidente. Detectar que una de estas dependencias cambió de comportamiento en producción, no solo en el momento de instalarla, es trabajo de telemetría continua; el curso de ingeniería de detección para SOC de este centro entra en cómo se diseña esa vigilancia.

El registro de modelos de la organización

Todo lo anterior de este módulo asume que alguien, dentro de la organización, puede responder a una pregunta simple: ¿qué modelo exacto, de qué versión, con qué procedencia verificada, está sirviendo esta aplicación en producción ahora mismo? En la mayoría de organizaciones que no lo han montado a propósito, nadie puede responder a esa pregunta con precisión, y es, con diferencia, el control que primero pide una auditoría y el que casi nunca existe todavía.

El AI Risk Management Framework de NIST, que el módulo 2 de este curso ya situó dentro del mapa de marcos de referencia, dedica tres subcategorías concretas de su función de gobierno a exactamente esto. GOVERN 1.6 pide mecanismos para inventariar los sistemas de IA, con recursos dedicados según la prioridad de riesgo de la organización; el propio marco describe ese inventario como una base de datos organizada de artefactos relacionados con un sistema o modelo de IA, que puede incluir documentación del sistema, planes de respuesta a incidentes, diccionarios de datos y los contactos de quien es responsable de mantenerlo. GOVERN 1.7 pide procesos para retirar y dar de baja sistemas de IA de forma segura y sin aumentar el riesgo ni reducir la confianza en la organización, con una advertencia explícita: terminar o borrar un modelo de forma irregular o indiscriminada puede ser tan arriesgado como no retirarlo nunca, porque otros sistemas pueden depender de él sin que quede documentado en ningún sitio. Y GOVERN 5.2 pide políticas de aprobación, aprobación condicional y rechazo para el diseño, la implementación y el despliegue de cada sistema de IA, antes de que llegue a producción, no después.

Un registro de modelos que cumpla estas tres subcategorías necesita, como mínimo, cuatro cosas por cada modelo: un identificador único y su versión exacta, la procedencia verificada tal como la desarrolló este módulo (publicador, licencia, formato, firma), quién aprobó su paso a producción y con qué evaluación, y un procedimiento documentado de retirada que no dependa de que alguien se acuerde de hacerlo bien cuando llegue el momento. Herramientas como MLflow ya implementan una parte técnica de esto con su registro de modelos: cada versión queda numerada y trazable, y en vez del antiguo sistema de etapas fijas (desarrollo, ensayo, producción, archivado), la versión actual del proyecto usa alias reasignables, como marcar qué versión concreta es la «campeona» en producción en un momento dado, consultable por ese alias desde el código en vez de por un número de versión que hay que recordar. La herramienta resuelve la parte de trazabilidad técnica; la aprobación y el procedimiento de retirada siguen siendo una decisión de la organización que ninguna herramienta toma en su lugar.

El curso de GRC de este mismo centro desarrolla cómo se construye un programa de gestión de riesgo a nivel de toda la organización, con sus roles y su cadencia de revisión; lo específico de este módulo es que ese programa, aplicado a la IA, tiene que apoyarse en el registro de modelos como su fuente de verdad, no en una hoja de cálculo que alguien actualiza cuando se acuerda. Y cuando el motivo de una retirada es que apareció evidencia de que un modelo en producción estaba comprometido, ese procedimiento deja de ser un trámite administrativo y pasa a ser el punto de partida de una investigación; el curso de DFIR de este centro cubre cómo se conduce esa investigación una vez el incidente ya ocurrió.

La cadena completa, eslabón por eslabón

La tabla reúne cada pieza que ha aparecido en este módulo en un solo sitio, pensada para usarse como lista de comprobación al revisar una aplicación real.

Eslabón Qué puede fallar Qué control aplica Quién responde
Selección del modelo base Se adopta un modelo sin saber quién lo entrenó ni con qué licencia real Verificar procedencia (publicador, licencia, tarjeta de modelo) antes de aprobarlo Arquitectura de la aplicación, con apoyo legal
Formato de distribución de los pesos Un archivo pickle ejecuta código al deserializarlo Usar safetensors siempre que exista; tratar el pickle como un ejecutable sin firmar Equipo de plataforma de ML
Integridad del artefacto descargado El archivo se sustituyó en tránsito o en el repositorio de origen Firma verificable (OpenSSF Model Signing) y hash comprobado contra el publicado Equipo de plataforma / seguridad
Datos de preentrenamiento Contenido envenenado insertado a gran escala en el scraping web Casi ningún control real por parte de quien solo usa el modelo; exigir documentación al proveedor El proveedor del modelo, fuera del control directo del equipo de aplicación
Datos de ajuste fino y adaptadores LoRA Conjunto propio o adaptador de terceros con ejemplos manipulados o una puerta trasera Curar y versionar el corpus propio; validar cualquier adaptador externo antes de fusionarlo Equipo de ML de la organización
Corpus de recuperación en tiempo real Documento hostil indexado que envenena respuestas futuras Control de admisión sobre qué se indexa, con metadatos de procedencia (ver módulo 5) Equipo de la aplicación, dueño del corpus
Bibliotecas de orquestación y extensiones Dependencia desactualizada o comprometida que el agente importa y ejecuta Fijar versiones, revisar antes de actualizar, aplicar SP 800-218A Equipo de desarrollo
Servidores de herramientas de terceros Servidor que expone funciones no auditadas por el equipo propio Alcance mínimo y confirmación humana, igual que cualquier herramienta (ver módulo 6) Equipo de plataforma de agentes
Registro y aprobación en producción Nadie sabe qué versión de qué modelo está sirviendo una aplicación concreta Inventario obligatorio, aprobación antes de desplegar, procedimiento de retirada Gobierno de IA y propietario del sistema

Ejercicio: documenta la procedencia completa de un modelo abierto

Elige un modelo publicado en un repositorio abierto (Hugging Face es el más habitual, pero vale cualquier otro) y documenta su procedencia real, aplicando los criterios de este módulo. No hace falta descargar el modelo completo si pesa demasiado para tu equipo: la información de procedencia está casi siempre en los metadatos y en los archivos pequeños del repositorio, no en los propios pesos.

Primero, identifica al publicador y la licencia real. La página del modelo muestra un nombre de organización o de usuario, pero eso no siempre coincide con quién lo entrenó de verdad: comprueba si hay un enlace explícito a un artículo o a un repositorio de entrenamiento que lo confirme. Después abre el archivo de licencia del propio repositorio, no te fíes solo de la etiqueta que muestra la interfaz web, y compara sus condiciones reales con las cuatro libertades de la definición de código abierto de IA de la OSI: úsalo con cualquier fin, estúdialo, modifícalo, compártelo. Si al modelo le falta el código de entrenamiento o el detalle del dataset, es un modelo de pesos abiertos, no de código abierto, aunque el repositorio lo llame de otra forma.

huggingface-cli download nombre-organizacion/nombre-modelo 
  --include "*.json" "*.md" "*.txt" "LICENSE*" 
  --local-dir ./procedencia-modelo

Segundo, comprueba el formato de distribución. Lista los archivos del repositorio y anota si los pesos están en .safetensors, en .bin o .pt (formato pickle), o en ambos a la vez. Si hay ambos, usa siempre el safetensors; si solo hay pickle, apunta ese hecho como un riesgo real de la procedencia, no como un detalle menor.

ls -la ./procedencia-modelo
python -c "from safetensors import safe_open; f = safe_open('modelo.safetensors', framework='pt'); print(list(f.keys())[:5])"

Tercero, busca cualquier verificación de integridad disponible. Comprueba si el repositorio publica hashes SHA-256 de los archivos, si los commits están firmados, o si existe una firma con OpenSSF Model Signing o un mecanismo equivalente. La inmensa mayoría de modelos hoy no tendrán nada de esto, y ese hallazgo, la ausencia y no solo la presencia, es parte del resultado que tienes que documentar.

sha256sum ./procedencia-modelo/*.safetensors

Cuarto, y el paso que de verdad importa, escribe un documento corto, media página basta, con cinco apartados: publicador y cómo lo verificaste, licencia real y qué permite, formato de distribución con su riesgo asociado, qué integridad se puede comprobar hoy, y una sección final titulada exactamente «No se puede verificar» con cada pregunta de este módulo que no tiene respuesta para ese modelo en concreto (de qué datos exactos vio el preentrenamiento, si algún colaborador tuvo motivo para introducir una puerta trasera, si el hash publicado se generó de forma independiente al propio publicador o solo por él). Ese último apartado no es un fallo del ejercicio: es el resultado más honesto que puede dar cualquier revisión de procedencia con la información que existe hoy en el ecosistema de modelos abiertos.

Preguntas frecuentes

¿Un modelo publicado bajo licencia MIT o Apache 2.0 ya es seguro de usar?

No, son cosas distintas. La licencia regula qué se puede hacer legalmente con el modelo (usarlo en un producto comercial, modificarlo, redistribuirlo); no dice nada sobre si los pesos vienen en un formato que ejecuta código al cargarlos, si la procedencia está verificada, o si el propio modelo se entrenó con una puerta trasera. Una licencia permisiva y un modelo comprometido no son contradictorios: pueden coexistir en el mismo archivo.

¿Si uso siempre archivos safetensors ya no tengo que preocuparme por la procedencia del modelo?

No. Safetensors resuelve un problema concreto, que cargar el archivo no ejecute código, y lo resuelve bien. No dice nada sobre si los números que contiene codifican un comportamiento que alguien introdujo a propósito durante el entrenamiento. Las dos comprobaciones son independientes: un modelo puede venir en un formato perfectamente seguro de cargar y tener, aun así, una puerta trasera entrenada en sus pesos.

¿Puedo revisar yo mismo los datos de preentrenamiento antes de confiar en un modelo?

Para un modelo de fundación de un tercero, no de forma realista. Cuando el propio dataset tiene billones de tokens recogidos de miles de fuentes, ninguna revisión manual de un equipo de aplicación llega a cubrirlo, y la mayoría de publicadores tampoco documenta el detalle completo. Es exactamente la asimetría de control que desarrolla este módulo: el preentrenamiento hay que confiarlo a la procedencia y a la disciplina de quien lo hizo, no intentar auditarlo después con los medios de un equipo que solo consume el modelo.

¿Qué diferencia hay entre pesos abiertos y un modelo de código abierto de verdad?

Un modelo de pesos abiertos publica el resultado del entrenamiento, listo para descargar y usar. Un modelo de código abierto, según la definición que fijó la Open Source Initiative en octubre de 2024, tiene que publicar también el código de entrenamiento y el detalle de los datos suficiente para que alguien con los recursos necesarios pudiera reconstruir un modelo equivalente por su cuenta. La mayoría de modelos que el sector llama «abiertos» cumplen solo la primera definición.

¿El registro de modelos es responsabilidad del equipo de seguridad o del equipo de datos?

De ninguno de los dos en exclusiva, y ahí falla en la práctica la mayoría de intentos de montarlo. El inventario y la trazabilidad técnica suelen depender de quien construye y despliega el modelo; la aprobación antes de producción y el criterio de cuándo retirarlo son decisiones de gobierno de riesgo que necesitan a alguien con autoridad para decir que no. Un registro que solo lleva el equipo técnico se convierte en documentación sin consecuencias; uno que solo lleva gobierno, sin datos técnicos actualizados, se queda desfasado en semanas.

¿Las herramientas de terceros que usa un agente son parte de esta cadena de suministro o del problema de agencia excesiva del módulo 6?

De las dos cosas a la vez, cada una en su capa. Que un servidor de herramientas de terceros sea código sin auditar que la aplicación ejecuta es un problema de cadena de suministro, el que cubre este módulo: hay que tratarlo con la misma disciplina de procedencia y control de versiones que cualquier otra dependencia. Qué puede hacer esa herramienta una vez se invoca, con qué alcance y con qué confirmación, es agencia excesiva, el problema que desarrolla el módulo 6. Un servidor de herramientas comprometido necesita las dos capas de defensa a la vez para no causar daño: que nunca debería haber entrado en la aplicación, y que si entra, no debería poder hacer más de lo estrictamente necesario.