Módulo 5: Securing The Ai Workload
7. STRIDE, revisitado: las amenazas específicas de una carga de IA
Descripción
THREAT-MODEL.md (cloud-security-and-guardrails-guide, Módulo 1, lección 7) tiene siete filas —TM-01 a TM-07—, cada una mapeada a una categoría de STRIDE, con su evidencia y su módulo de mitigación. Ninguna de las siete menciona un modelo de lenguaje, porque cuando ese documento se escribió, Andes Cargo todavía no tenía ninguna carga de IA generativa. Esta lección no reescribe el documento ni renumera nada existente: agrega dos filas nuevas, TM-08 y TM-09, cada una con la misma disciplina de evidencia verificable que las siete originales ya establecieron.
Conexión con el módulo
Las dos filas nuevas de esta lección no son hipótesis sin anclaje — cada una cita el control real que ya la mitiga, construido en un módulo anterior de esta guía: el guardrail gestionado de Bedrock (Módulo 4) para TM-08, y el scrubber de PII propio (Módulo 4, lección 5) para TM-09. Esta lección documenta lo que ya existe, con el mismo formato que cloud-security-and-guardrails-guide, Módulo 1, lección 7 ya estableció — no construye ningún control nuevo.
Por qué STRIDE necesita dos filas nuevas, no una reescritura completa
cloud-security-and-guardrails-guide, Módulo 1, lección 3, ya explicó las seis categorías de STRIDE: Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege. Ninguna categoría es exclusiva de infraestructura "tradicional" frente a infraestructura de IA — STRIDE es un marco general, aplicable a cualquier sistema. Lo que cambia, al agregar una carga de IA generativa, no es el marco: es que dos de las seis categorías adquieren una manifestación nueva, específica de invocar un modelo no determinista, que las siete filas originales —escritas antes de que Bedrock existiera en este proyecto— nunca pudieron cubrir.
LAS SIETE FILAS ORIGINALES LAS DOS FILAS NUEVAS DE ESTE MÓDULO
TM-01 Spoofing (M2) TM-08 Tampering
TM-02 Tampering (M6) del *prompt* -- específico de invocar
TM-03 Repudiation (M7) un modelo, nunca existió antes de esta
TM-04 Information disc. (M4) guía
TM-05 Information disc. (M3)
TM-06 Denial of service (M4) TM-09 Information disclosure
TM-07 Elevation priv. (M2) de PII en un manifiesto de texto libre --
distinto de TM-04/TM-05 (ambas de
infraestructura, no de contenido)
TM-02 ya cubre Tampering del artefacto de despliegue (function.zip sin firmar, resuelto por cosign en el Módulo 6 de esa guía) — pero nunca contempló que el contenido de una solicitud a un modelo pudiera manipularse para hacer que el sistema actúe fuera de su propósito. TM-04 y TM-05 ya cubren Information disclosure de infraestructura (un bucket sin bloqueo de acceso público, credenciales en texto plano) — pero ninguna de las dos contempló que un manifiesto de texto libre, el mismo tipo de dato que motiva esta guía entera (Módulo 1, lección 3), pudiera traer PII incidental que un modelo de lenguaje procese y, potencialmente, repita de vuelta.
TM-08 — Tampering: intento de manipulación del prompt
Categoría: Tampering. Hallazgo: extract-shipment-manifest-fields recibe texto libre no controlado —el cuerpo de un correo, una nota copiada de un sistema de un socio logístico (Módulo 1, lección 3)— como entrada directa a un modelo de lenguaje. Sin ningún control, ese texto podría contener instrucciones diseñadas para hacer que el modelo ignore su tarea real (extraer campos de un manifiesto) y en su lugar siga instrucciones inyectadas por quien escribió el manifiesto — un intento de ataque de prompt, la misma clase de amenaza que el Módulo 4, lección 7 de esta guía ya construyó como ejemplo representativo.
Evidencia: bedrock.tf (Módulo 4, lección 3) declara content_policy_config con un filters_config de type = "PROMPT_ATTACK", input_strength = "HIGH" — la existencia misma de esa política, con esa configuración específica, es la evidencia documentada de que este riesgo se identificó y se diseñó una mitigación para él, antes de que este módulo llegara a documentarlo formalmente en THREAT-MODEL.md.
Impacto: Sin este control, un manifiesto malicioso podría hacer que el modelo revele información del sistema (un prompt del sistema, si existiera uno más elaborado), o produzca una salida que no corresponde en absoluto a la extracción de campos esperada —potencialmente escribiendo datos incorrectos o maliciosos en Shipments si post_invoke_checks.py no lo detuviera primero—.
Mitigado en: Módulo 4, lección 3 (content_policy_config, filtro PROMPT_ATTACK, HCL declarado y plan-eado real) — con la honestidad exacta que el Módulo 4, lección 7 de esta guía ya estableció: el bloqueo real de un intento de ataque de prompt solo se puede confirmar invocando el modelo de verdad, algo que este laboratorio $0 nunca hace. La mitigación está declarada como código, verificada con terraform validate/plan; su efectividad contra un ataque real queda representativa, citada con precisión contra el schema oficial de ApplyGuardrail.
TM-09 — Information disclosure: fuga de PII incidental en un manifiesto
Categoría: Information disclosure. Hallazgo: un manifiesto de texto libre real, del tipo que motiva esta guía, con frecuencia contiene datos de contacto incidentales —un correo electrónico, un número de teléfono— insertados naturalmente en la prosa de quien lo escribió, sin ninguna intención maliciosa. Sin ningún control, ese texto viajaría, tal cual, hasta el modelo de Bedrock, y potencialmente aparecería de vuelta en la respuesta o en cualquier registro (log) que el sistema genere.
Evidencia: guardrails/pre_invoke_checks.py (Módulo 4, lección 5) existe precisamente porque este riesgo se identificó como real y concreto, no hipotético — el propio script detecta y redacta correos y teléfonos con expresiones regulares, corrido y verificado con pytest contra un manifiesto real del Módulo 1 (envío AC-4471) que contiene, a propósito, un correo y un teléfono en su prosa.
Impacto: Un dato de contacto personal —correo, teléfono— podría quedar expuesto en una respuesta del modelo, en un registro de invocación, o en cualquier sistema que reciba el texto sin redactar, violando la expectativa razonable de privacidad de quien escribió el manifiesto, sin que esa persona supiera que su información personal iba a viajar hasta un servicio de inferencia de terceros.
Mitigado en: dos capas independientes, ninguna sustituta de la otra (el mismo argumento de defensa en profundidad que el Módulo 4, lección 4 de esta guía ya desarrolló): guardrails/pre_invoke_checks.py (determinista, propio, corre siempre, sin importar si Bedrock existe) y sensitive_information_policy_config de bedrock.tf con EMAIL/PHONE en ANONYMIZE (gestionado, probabilístico, evaluado por Bedrock mismo). A diferencia de TM-08, esta fila tiene una mitigación que sí se puede confirmar completamente ejecutada, sin ninguna parte representativa: pre_invoke_checks.py corrió de verdad, con pytest, y el resultado (PII FOUND, EMAIL matches: 1, PHONE matches: 1, texto redactado) es literal, no una construcción sobre un schema documentado.
Actualizando THREAT-MODEL.md: las dos filas nuevas
| TM-06 | Denial of service | No control blocks a `plan` that destroys `Shipments` | No preventive policy evaluates `resource_changes[].actions` before `apply` | A bad `apply` -- human error or a misled agent -- removes the system's sole source of shipment state | Module 4 (`no-destroy-shipments.rego`) |
| TM-07 | Elevation of privilege | `AppServerRole` has the same full-bucket scope as `LambdaManifestProcessorRole` | `AppServerRole-policy` == `LambdaManifestProcessorRole-policy` (same actions, same resource ARNs) | A compromise of the read-only tracking app grants access to raw manifests it never needed to read | Module 2, lesson 7 (least-privilege role tightening) |
+ | TM-08 | Tampering | Free-text manifest content could carry a prompt injection attempt against the extractor's model call | `bedrock.tf`, `content_policy_config.filters_config` (`type = "PROMPT_ATTACK"`, `input_strength = "HIGH"`) -- genai-on-aws-production-guide, Module 4, lesson 3 | An attacker-controlled manifest could redirect the model away from field extraction toward following injected instructions | genai-on-aws-production-guide, Module 4, lesson 3 (declared, `validate`/`plan` real; real blocking representative -- Module 4, lesson 7) |
+ | TM-09 | Information disclosure | A free-text manifest routinely carries a sender's email or phone number embedded in the prose, reaching an inference service outside this account | `guardrails/pre_invoke_checks.py` (EMAIL/PHONE regex, pytest-verified) + `bedrock.tf` `sensitive_information_policy_config` (EMAIL/PHONE, ANONYMIZE) -- genai-on-aws-production-guide, Module 4, lessons 3 and 5 | A shipper's personal contact data could leak into a model response or an invocation log | genai-on-aws-production-guide, Module 4, lessons 3 and 5 (defense in depth, both layers executed) |
Fíjate en un detalle que vale la pena nombrar con precisión: a diferencia de las siete filas originales, cuya columna "Mitigated in" apunta a un módulo de la misma guía (cloud-security-and-guardrails-guide), estas dos filas apuntan a módulos de esta guía (genai-on-aws-production-guide). Esto es correcto, no un error de formato: THREAT-MODEL.md es un documento compartido del proyecto andes-cargo-infra/, y cualquier guía que agregue infraestructura nueva a ese mismo proyecto —esta guía incluida— tiene la misma responsabilidad de mantenerlo actualizado que cloud-security-and-guardrails-guide, Módulo 1, lección 7, sección 6 ("Document maintenance") ya declaró explícitamente: "reviewed, not rewritten from scratch, whenever a new resource is added to andes-cargo-infra/".
Verificando el documento actualizado
grep -c '^| TM-' THREAT-MODEL.md
Qué esperar (literal — nueve filas, las siete originales más las dos de esta lección; el contenido de este documento lo escribiste tú, así que su forma es determinista):
9
Errores comunes
Renumerar las siete filas originales para "reorganizar" el documento por orden de guía, en vez de agregar al final (de tocar lo que no te corresponde tocar). Qué pasa: alguien, viendo que las dos filas nuevas pertenecen a una guía distinta, intenta reordenar THREAT-MODEL.md agrupando las filas por guía de origen, renumerando TM-01 a TM-09 en un orden distinto. Cómo detectarlo: si tu versión de THREAT-MODEL.md tiene identificadores TM-* que no coinciden con los que cloud-security-and-guardrails-guide, Módulo 1, lección 7 ya fijó para las siete filas originales. Cómo corregirlo: los identificadores TM-01 a TM-07 son permanentes, exactamente como esa lección ya lo declaró — "a partir de este documento, cualquier módulo posterior de esta guía puede referirse a 'TM-06' sin tener que reexplicar qué es cada vez". Renumerar rompería cualquier referencia existente a esos identificadores en otros documentos del proyecto. Las filas nuevas siempre se agregan al final, con el siguiente número disponible.
Escribir TM-08/TM-09 sin citar el archivo o recurso exacto que los mitiga, repitiendo el error que cloud-security-and-guardrails-guide, Módulo 1, lección 7 ya advirtió (de vaguedad en la evidencia). Qué pasa: alguien escribe un hallazgo genérico como "el modelo podría ser manipulado" sin nombrar el archivo, la línea, o el argumento HCL específico que lo mitiga. Cómo detectarlo: si tu fila de TM-08/TM-09 no incluye un nombre de archivo verificable (bedrock.tf, pre_invoke_checks.py) que alguien podría abrir y confirmar. Cómo corregirlo: cada fila de esta lección cita el archivo y el argumento exacto (content_policy_config.filters_config, sensitive_information_policy_config) — la misma especificidad que separa un modelo de amenazas real de una lista de preocupaciones sin anclaje, la misma disciplina que ese documento estableció desde su primera versión.
Confundir TM-08 con un duplicado de TM-02 (Tampering, el artefacto de despliegue) porque ambos usan la misma categoría STRIDE (de agrupar por categoría en vez de por mecanismo). Qué pasa: alguien, viendo que TM-02 y TM-08 comparten la categoría Tampering, asume que son el mismo riesgo documentado dos veces. Cómo detectarlo: si tu explicación de por qué existen ambas filas no distingue qué se manipula en cada caso. Cómo corregirlo: TM-02 es tampering del artefacto binario —el .zip desplegado, resuelto con firma criptográfica (cosign)—; TM-08 es tampering del contenido de una solicitud a un modelo —el texto de un manifiesto, resuelto con un filtro de contenido (content_policy_config)—. STRIDE agrupa amenazas por mecanismo de ataque (manipular algo que debería permanecer íntegro), no por superficie específica — dos filas distintas, de la misma categoría, cubriendo superficies completamente distintas, es exactamente cómo STRIDE está diseñado para usarse.
Ejercicios
Ejercicio 1 — Sin mirar esta lección, escribe de memoria las dos categorías STRIDE que TM-08 y TM-09 usan. Después, verifica tu respuesta y explica por qué ninguna de las dos es Denial of service ni Elevation of privilege, las dos categorías que a primera vista también podrían parecer relevantes para una carga de IA.
Ver solución
TM-08 es Tampering, TM-09 es Information disclosure. Denial of service no aplica porque ningún riesgo de esta lección describe una forma de dejar el sistema sin servicio —un intento de ataque de prompt no tumba extract-shipment-manifest-fields, en el peor caso produce una respuesta incorrecta que post_invoke_checks.py (Módulo 4, lección 6) rechazaría—. Elevation of privilege tampoco aplica porque ninguno de los dos riesgos describe a alguien obteniendo permisos que no debería tener —eso ya lo cubre TM-07, y la lección 2/3 de este módulo, con bedrock-least-privilege.rego, es la que vigila esa categoría específica para la infraestructura de IA—.
Ejercicio 2 — Explica por qué TM-09 tiene una mitigación completamente ejecutada (sin ninguna parte representativa) mientras que TM-08 sí tiene una parte representativa. Retoma la tabla de honestidad del DISENO.md de esta guía para responder con precisión.
Ver solución
pre_invoke_checks.py (la mitigación principal de TM-09) es código Python puro, determinista, que corre completamente offline, sin depender de Bedrock en absoluto — se puede probar de punta a punta con pytest, y el resultado (PII FOUND, correos y teléfonos detectados y redactados) es tan literal como cualquier otro resultado de este ecosistema. TM-08, en cambio, se mitiga principalmente con content_policy_config de Bedrock Guardrails —un mecanismo gestionado, que solo se puede confirmar bloqueando de verdad cuando el modelo real lo evalúa—; la declaración en HCL es real y ejecutada, pero su efectividad contra un ataque real depende de invocar Bedrock, algo que este laboratorio $0 nunca hace (Módulo 4, lección 7 de esta guía). La diferencia no es de calidad del control, es de qué tan verificable es sin necesitar una invocación real.
Ejercicio 3 — Diseña, en prosa, una fila TM-10 hipotética que este módulo NO cubrió, relacionada con la disponibilidad (no la seguridad) de la infraestructura de IA. Justifica por qué no era necesaria para el alcance de este módulo específico.
Ver solución
Una respuesta razonable: una fila TM-10 podría documentar el riesgo de que extract-shipment-manifest-fields alcance la cuota de invocaciones por minuto de Bedrock (nombrada en el Módulo 2, lección 3 de esta guía) durante un pico de manifiestos en texto libre, dejando manifiestos sin procesar hasta que la cuota se libere — una forma de Denial of service específica de un servicio usage-based, distinta de TM-06 (que protege contra la destrucción de la tabla Shipments, no contra un límite de tasa). No era necesaria para el alcance de este módulo porque este módulo se limita, con precisión, a extender el security gate heredado —policy-check/iac-scan/verify-artifact— a la infraestructura nueva; un riesgo de cuota de servicio pertenece más naturalmente al vocabulario de confiabilidad (SLI/SLO) que el Módulo 7 de esta guía construye, no al de seguridad de este módulo.
Resumen y siguiente paso
Esta lección agregó TM-08 (Tampering, intento de manipulación del prompt, mitigado por content_policy_config del Módulo 4) y TM-09 (Information disclosure, fuga de PII incidental, mitigada por dos capas independientes de defensa en profundidad) a THREAT-MODEL.md, sin renumerar ni tocar ninguna de las siete filas originales de cloud-security-and-guardrails-guide. Confirmaste, con grep -c, que el documento ahora tiene nueve filas — y viste, con precisión, por qué una carga de IA generativa necesita exactamente dos filas nuevas, no una reescritura completa del marco STRIDE.
Antes de avanzar deberías poder: citar los archivos exactos que mitigan TM-08 y TM-09; explicar por qué esas dos filas no renumeran las siete originales; y distinguir TM-08 de TM-02 a pesar de compartir categoría STRIDE.
La lección 8, el proyecto que cierra este módulo, corre los tres jobs del security gate heredado —con el Terraform y el artefacto de este módulo incluidos— de punta a punta, con act pull_request real.
Recursos
cloud-security-and-guardrails-guide, Módulo 1, lección 7 (07-hands-on-writing-the-threat-model-document.md) — el documento original que esta lección extiende, con las siete filas y la sección de mantenimiento que autoriza esta actualización.- Microsoft Learn — Threats: Microsoft Threat Modeling Tool — las definiciones de STRIDE, la misma fuente que la guía hermana ya citó.
- Módulo 4, lecciones 3, 5 y 7 de esta guía — el origen de cada mitigación citada en
TM-08yTM-09. - AWS Docs — Prompt injection — referencia oficial del mecanismo de detección de ataques de prompt que
TM-08cita.