OWASP A08 Fallos de Integridad
OWASP A08:2021 cubre ataques a pipelines CI/CD, deserialización insegura y SRI faltante. Aprende cómo ocurren los fallos de integridad y cómo prevenirlos.
Rod
Founder & Developer
OWASP A08:2021 — Fallos de Integridad de Software y Datos fue una categoría nueva en la edición 2021 del Top 10. La razón por la que entró ese año no es sutil: el ataque a SolarWinds en 2020 demostró que comprometer un pipeline de build es una forma más efectiva de atacar a miles de objetivos que atacarlos uno por uno. OWASP respondió creando una categoría específica para integridad — la suposición de que el código, los datos y las actualizaciones no fueron manipulados entre donde se originan y donde tu app los ejecuta.
Esta guía cubre cómo se ven los fallos de integridad OWASP A08 en la práctica, los ataques reales que hicieron necesaria la categoría, y los cambios específicos de código que los previenen. Sin explicaciones solo teóricas — cada sección termina con algo que puedes revisar o arreglar hoy.
Qué cubre OWASP A08 en realidad
La categoría tiene tres subproblemas principales:
Deserialización insegura — parsear datos controlados por el usuario en objetos estructurados sin validar la estructura primero. El exploit clásico aquí es crear un payload serializado que ejecuta código en el servidor cuando tu app lo deserializa. CWE-502 (Deserialización de Datos No Confiables) ha estado en el Top 25 de Debilidades Más Peligrosas de MITRE durante años.
Verificación de integridad faltante — cargar scripts desde un CDN, servicio de terceros, o registro de paquetes sin verificar que el archivo es lo que esperabas. Si el CDN es comprometido, tus usuarios ejecutan el código del atacante.
Fallos de integridad en pipelines CI/CD — ejecutar código en tu pipeline de build sin verificarlo. GitHub Actions sin pinear, scripts de build jalados de fuentes externas sin verificación, y mecanismos de actualización automática que no verifican firmas entran aquí.
La razón por la que estas tres cosas viven en la misma categoría de OWASP es el mismo patrón subyacente: tu app confía en algo sin verificarlo ciegamente. La solución en cada caso involucra alguna forma de verificación — hashing, verificación de firmas, o pinear a un estado conocido y bueno.
Cómo se ven los fallos de integridad en código real
SRI faltante en scripts de CDN
Este es el fallo de integridad más común en código front-end. Incluyes una librería de un CDN con un tag <script> sin más. Si el CDN es comprometido — o si el archivo es modificado en tránsito — tus usuarios ejecutan lo que sea que el CDN sirva. Sin error, sin advertencia.
<!-- MAL: Sin verificación de integridad — el CDN podría servir cualquier cosa -->
<script src="https://cdn.example.com/library.min.js"></script><!-- BIEN: El hash SRI hace que el navegador rechace cualquier cosa que no coincida -->
<script
src="https://cdn.example.com/library.min.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"
></script>El atributo integrity le dice al navegador: "calcula el hash del archivo que realmente recibiste, y si no coincide con este valor, no lo ejecutes." Es una verificación de integridad enforceada por el navegador. Subresource Integrity (SRI) es el nombre del spec — está soportado en todos los navegadores modernos y toma como dos minutos implementarlo. La mayoría de los CDN incluyen el hash SRI en su código de embed de copiar y pegar. Si el tuyo no, srihash.org los genera para cualquier URL.
El scanner de Data Hogo revisa scripts de CDN sin el atributo integrity. Hemos encontrado Subresource Integrity faltante en más del 60% de los repos front-end que hemos escaneado — es el hallazgo A08 más común.
Deserialización insegura de datos controlados por el usuario
La deserialización — convertir un string o stream de bytes de vuelta a un objeto estructurado — es una operación normal. El problema es hacerlo con datos de una fuente no confiable sin validar el resultado.
En JavaScript/TypeScript, JSON.parse() es técnicamente seguro contra exploits clásicos de ejecución remota de código (a diferencia de la deserialización en Java o PHP). Pero los devs frecuentemente tratan un objeto JSON parseado exitosamente como datos confiables, saltando la validación de su estructura y tipos. Ahí es donde ocurre el fallo de integridad.
// MAL: parsear y usar sin validación — el atacante controla la forma
const config = JSON.parse(req.body.settings);
db.query(`SELECT * FROM data WHERE user_id = ${config.userId}`);
// config.userId puede ser cualquier cosa — incluyendo '1 OR 1=1'// BIEN: parsear, luego validar schema y tipos con Zod antes de confiar en cualquier valor
import { z } from "zod";
const settingsSchema = z.object({
userId: z.string().uuid(),
theme: z.enum(["light", "dark"]),
pageSize: z.number().int().min(10).max(100),
});
const parsed = JSON.parse(req.body.settings);
const config = settingsSchema.parse(parsed); // lanza error si la forma es incorrecta
db.query("SELECT * FROM data WHERE user_id = $1", [config.userId]);El schema de Zod actúa como una verificación de integridad a nivel de tipos. No solo confías en que JSON.parse() produjo algo — verificas que lo que produjo coincide con la forma que tu código realmente espera. Aprende más sobre patrones de deserialización insegura y cómo aparecen en aplicaciones web modernas.
Para lenguajes con serialización más poderosa (Java's ObjectInputStream, PHP's unserialize(), Python's pickle), el riesgo es mucho mayor — la ejecución arbitraria de código en la deserialización está bien documentada y es activamente explotada. La solución ahí es usar formatos de serialización seguros (JSON, Protobuf) en lugar de serialización nativa del lenguaje para cualquier dato que cruce un límite de confianza.
GitHub Actions sin pinear
Los workflows de GitHub Actions jalan acciones externas usando una directiva uses:. La mayoría de los devs pinean a un tag de versión. El problema es que los tags son mutables — el autor de la acción puede mover el tag para que apunte a código completamente diferente.
# MAL: 'main' es lo que sea que la rama default del repo tenga ahora
- uses: actions/checkout@main
# TAMBIÉN MAL: los tags pueden moverse — v4 hoy podría apuntar a código diferente mañana
- uses: actions/checkout@v4# BIEN: el SHA es inmutable — este hash exacto no puede ser reemplazado silenciosamente
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2Una GitHub Action comprometida corre dentro de tu entorno CI/CD con acceso a tus secrets, tu código fuente, y tu pipeline de deployment. El GITHUB_TOKEN, tus credenciales de nube, tus llaves de firma — todo es accesible para código corriendo en tu workflow. Una acción maliciosa puede exfiltrar secrets, modificar tus artefactos de build, o inyectar código en tu aplicación deployada.
Aprende más sobre GitHub Actions sin pinear y cómo auditar tus workflows sistemáticamente.
El patrón en los tres casos: estás confiando en algo externo sin verificar su integridad. Scripts de CDN, datos deserializados del usuario, acciones CI/CD — misma categoría, mismo patrón de solución.
Los ataques reales que hicieron necesario A08
SolarWinds Orion (2020)
El ataque a SolarWinds es la demostración más clara del mundo real de por qué OWASP creó A08. Los atacantes — luego atribuidos al SVR ruso — comprometieron el sistema de build de software de SolarWinds. Inyectaron código malicioso en una actualización legítima de la plataforma Orion, una herramienta de monitoreo de red usada por aproximadamente 18,000 organizaciones, incluyendo agencias federales de EE.UU.
La actualización comprometida fue firmada con el propio certificado de SolarWinds, pasó todas las verificaciones de integridad que los destinatarios tenían implementadas, y fue distribuida a través del canal oficial de actualizaciones de SolarWinds. Porque las organizaciones confiaban en el mecanismo de actualización, lo instalaron sin cuestionarlo.
La lección no es que todos los mecanismos de actualización sean inherentemente inseguros. Es que confiar en un mecanismo sin verificar lo que entrega es un fallo de integridad — y que los pipelines de build son objetivos de alto valor porque comprometerlos significa atacar a todos los usuarios posteriores simultáneamente.
Codecov Bash Uploader (2021)
En abril de 2021, atacantes obtuvieron acceso a la infraestructura CI/CD de Codecov y modificaron el script bash uploader que miles de empresas usaban en sus pipelines. El script modificado exfiltraba variables de entorno — incluyendo credenciales de nube, API keys y tokens — a un servidor controlado por los atacantes.
El ataque persistió durante dos meses antes de ser descubierto. Empresas como Twilio, HashiCorp y Rapid7 confirmaron que fueron afectadas. Las credenciales exfiltradas fueron usadas para ataques posteriores.
Este es un fallo A08 de manual: los devs hacían curl de un script de los servidores de Codecov y lo pipeaban directamente a bash, sin verificar su integridad:
# MAL: descargar y ejecutar sin ninguna verificación de integridad
curl -s https://codecov.io/bash | bash# BIEN: descargar, verificar hash, luego ejecutar
curl -o codecov.sh https://codecov.io/bash
sha512sum -c <(echo "hashesperado codecov.sh")
bash codecov.shNadie que hace pipe de un script remoto a bash está pensando en supply chain attacks en el momento. Ese es exactamente el tipo de suposición que A08 cuestiona.
Ataque de Supply Chain a 3CX (2023)
En marzo de 2023, el cliente desktop de 3CX — una aplicación VoIP con millones de usuarios — fue comprometido a través de un ataque de supply chain. Los atacantes primero comprometieron un software de trading llamado Trading Technologies, inyectaron una DLL maliciosa en él, y un empleado de 3CX descargó e instaló ese software. La DLL maliciosa eventualmente llegó al proceso de build de 3CX y fue enviada como parte de una actualización firmada de 3CX.
El ataque a 3CX demostró que los supply chain attacks pueden encadenarse: comprometer al proveedor A para atacar al proveedor B para atacar a los clientes del proveedor B. Las verificaciones de integridad en cada eslabón de la cadena habrían detenido la propagación del ataque.
Prevención: qué hacer en concreto
1. Agregar SRI a cada script externo
Para cada tag <script> o <link> que carga desde un CDN o host de terceros:
<!-- Genera el hash del archivo real, no de la URL -->
<script
src="https://cdn.jsdelivr.net/npm/alpinejs@3.14.3/dist/cdn.min.js"
integrity="sha384-QQpNPmEhbBnMDFwTfSFBs/OosMH9PJQRTS9B7tHgM8jqTFMxBnS7EFZ+EfcNpIM"
crossorigin="anonymous"
defer
></script>Si usas un bundler (webpack, Vite, esbuild), prefiere importar paquetes a través de npm en lugar de cargarlos desde un CDN. Obtienes mejor control de versiones y el bundler maneja la integridad implícitamente al incluir el archivo en tu artefacto de build.
2. Pinear GitHub Actions al SHA — automatízalo
Pinear cada acción manualmente es tedioso y propenso a errores. Usa Dependabot para actualizaciones automatizadas de pines de SHA, o la acción step-security/harden-runner para auditar tu workflow en tiempo de ejecución.
Tu .github/dependabot.yml:
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
groups:
actions:
patterns:
- "*"Con esta configuración, Dependabot abre PRs para mantener tus SHAs pineados actualizados cuando se lanzan nuevas versiones. Obtienes inmutabilidad sin mantenimiento manual.
3. Validar todo lo que deserializas
Cualquier dato que cruce un límite de confianza — cuerpos de requests HTTP, query parameters, cookies, datos de APIs externas, items leídos de una cola — debe ser validado después de parsearlo y antes de usarlo.
En TypeScript, Zod es el estándar. Define schemas que coincidan exactamente con lo que tu código espera, parsea los datos entrantes a través de ellos, y deja que el ZodError lanzado aparezca como un 400 Bad Request en lugar de un crash o un error lógico.
import { z } from "zod";
// Define exactamente qué forma esperas
const webhookPayloadSchema = z.object({
event: z.enum(["push", "pull_request", "release"]),
repository: z.object({
id: z.number().int().positive(),
full_name: z.string().max(200),
}),
sender: z.object({
id: z.number().int().positive(),
login: z.string().max(100),
}),
});
// Parsea antes de usar — lanza error si la forma es incorrecta
const payload = webhookPayloadSchema.parse(JSON.parse(rawBody));4. Verificar checksums para artefactos descargados
Cualquier paso de build que descargue un binario, archivo comprimido o script debe verificar su checksum antes de usarlo:
# Descargar el binario
curl -LO https://releases.example.com/tool-v1.2.3-linux-amd64.tar.gz
# Verificar el checksum contra el valor publicado
echo "hashsha256esperado tool-v1.2.3-linux-amd64.tar.gz" | sha256sum -c
# Solo continuar si la verificación pasó
tar -xzf tool-v1.2.3-linux-amd64.tar.gzPara imágenes Docker, pinea al digest de la imagen en lugar del tag:
# MAL: el tag 'latest' se actualiza cuando el mantenedor hace push
FROM node:22-alpine
# BIEN: el digest es inmutable
FROM node:22-alpine@sha256:a4b1c2d3e4f5...5. Auditar tu pipeline CI/CD para encontrar suposiciones de confianza
Recorre cada paso de tu pipeline CI/CD y pregunta: "¿En qué estoy confiando aquí sin verificación?" Las respuestas comunes incluyen:
- Acciones externas pineadas a tags en lugar de SHAs
- Patrones
curl | bashpara instalar herramientas - Instalación de paquetes sin verificación de lockfile (
npm installen lugar denpm ci) - Artefactos de build subidos a registros sin firma
El objetivo no es paranoia — es identificar dónde un atacante podría inyectar código que corre en tu entorno de pipeline.
Cómo Data Hogo escanea para A08
Data Hogo revisa varios patrones A08 automáticamente:
- Fallos de integridad de datos — patrones generales donde los datos se procesan sin verificación de integridad
- Subresource Integrity faltante — tags de script y stylesheet de CDN sin atributos
integrity - Deserialización insegura — deserialización de input controlado por el usuario sin validación de schema
- GitHub Actions sin pinear — pasos de workflow usando referencias a tags en lugar de pines de SHA
Cuando escaneamos 50 repos públicos durante el desarrollo, GitHub Actions sin pinear fue el hallazgo más común — presente en el 78% de repos con workflows de GitHub Actions. SRI faltante llegó en segundo lugar. La mayoría de los devs simplemente no han pensado en estos como problemas de seguridad, porque el camino de explotación no es tan obvio como SQL injection o API keys expuestas.
Escanea tu repo gratis para ver cuáles tiene tu proyecto. El escaneo toma menos de 60 segundos y cubre patrones A08 junto con secrets, dependencias, y vulnerabilidades a nivel de código.
El panorama más amplio: CI/CD es la nueva superficie de ataque
Antes de que OWASP agregara A08, la conversación de seguridad era principalmente sobre la aplicación en ejecución — autenticación, inyección, control de acceso. A08 cambia la atención a la supply chain: todas las herramientas, dependencias y automatización que construyen y deployean la aplicación.
Los ataques a SolarWinds y Codecov ocurrieron en 2020 y 2021. Desde entonces, los supply chain attacks han aumentado significativamente. El patrón es consistente: a los atacantes les resulta más eficiente comprometer las herramientas de desarrollo que atacar cada aplicación individualmente.
Tu pipeline CI/CD corre con acceso elevado. Lee tus secrets, construye tus artefactos, y deploya a producción. Ejecuta código de GitHub Actions, scripts de npm, imágenes Docker, y binarios descargados. Cada cosa externa que ejecuta sin verificación es un fallo de integridad potencial.
Las soluciones no son complicadas. Pinear a un SHA toma 30 segundos. Agregar un hash SRI toma dos minutos. Validar datos deserializados con Zod toma cinco minutos por endpoint. Son el tipo de mejoras de bajo esfuerzo que reducen significativamente tu exposición a toda una categoría de ataques.
Si quieres ver cómo está tu proyecto actualmente en A08, escanea tu repo con Data Hogo. Tendrás hallazgos en menos de un minuto — incluyendo qué archivos y líneas específicas necesitan atención.
Preguntas frecuentes
¿Qué es OWASP A08:2021 Fallos de Integridad de Software y Datos?
OWASP A08:2021 es una categoría que cubre vulnerabilidades donde el código o los datos pueden ser modificados sin ninguna verificación. Incluye SRI faltante en scripts de CDN, deserialización insegura de datos controlados por el usuario, pipelines CI/CD que ejecutan código sin verificar, y mecanismos de actualización automática que no verifican la autenticidad. Fue nueva en el OWASP Top 10 de 2021, impulsada principalmente por ataques de supply chain como SolarWinds.
¿Qué es un ataque de supply chain y cómo se relaciona con OWASP A08?
Un ataque de supply chain ocurre cuando un atacante compromete una dependencia, herramienta de build o script de terceros en la que confía tu aplicación. En lugar de atacar tu app directamente, corrompen algo que tu app jala. OWASP A08 cubre esto porque el problema central es la integridad — tu app está jalando código o datos sin verificar que no fueron manipulados. El ataque a SolarWinds Orion (2020) y la brecha de Codecov (2021) son los ejemplos más citados.
¿Cómo agrego Subresource Integrity (SRI) a un script de CDN?
Genera un hash del archivo del script usando sha384 o sha512, luego agrégalo como atributo integrity en tu tag script: <script src="https://cdn.example.com/lib.js" integrity="sha384-[hash]" crossorigin="anonymous"></script>. Si el archivo entregado por el CDN no coincide con el hash, el navegador rechaza ejecutarlo. La mayoría de los CDN muestran el hash SRI junto a su código de embed. También puedes generar hashes usando srihash.org.
¿Por qué es más seguro pinear GitHub Actions a un commit SHA que a un tag de versión?
Un tag de versión como actions/checkout@v4 es un puntero mutable — el dueño del repo puede moverlo para que apunte a código diferente en cualquier momento. Un commit SHA como actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 es inmutable. Esto importa porque una GitHub Action comprometida corre dentro de tu entorno CI/CD con acceso a todos tus secrets y tu pipeline de deployment. Pinear por SHA es la única forma de garantizar que ejecutas exactamente el código que revisaste.
¿Qué es la deserialización insegura y por qué es peligrosa?
La deserialización es convertir datos almacenados o transmitidos de vuelta a un objeto que tu código puede usar. La deserialización insegura ocurre cuando deserializas datos de una fuente no confiable sin validar su estructura primero. Un atacante puede crear un payload que, al deserializarse, ejecuta código arbitrario, bypasea autenticación, o corrompe el estado de la aplicación. CWE-502 (Deserialización de Datos No Confiables) está consistentemente en el Top 25 de Debilidades Más Peligrosas de MITRE. La solución es validar la estructura de los datos deserializados con un schema antes de usar cualquier valor.
Posts Relacionados
OWASP A03 Ataques de Inyección
OWASP A03:2021 Inyección cubre SQL, NoSQL, XSS, inyección de comandos y más. Código vulnerable vs. seguro en Node.js, un breach real, y cinco estrategias de prevención.
OWASP A05 Configuración Insegura
El 90% de las aplicaciones tiene alguna configuración insegura. Aprende qué cubre OWASP A05:2021, ve el código vulnerable vs. seguro en Next.js, y corrígelo ya.
OWASP A01 Control de Acceso Roto
El control de acceso roto es el riesgo #1 del OWASP Top 10. Esta guía explica IDOR, JWT tampering y rutas sin auth — con ejemplos reales en Next.js y cómo corregirlos.