Módulo 6: Supply Chain Sbom And Signing

2. Qué es un SBOM y por qué importa

Descripción

function.zip —el artefacto de 890 bytes que Lambda ejecuta— parece, a simple vista, un solo archivo: handler.py, comprimido. Pero ese .zip no corre solo: en el entorno de ejecución de Lambda, handler.py hace import boto3, y boto3 no es una sola pieza de código — es una raíz que, al resolverse, arrastra media docena de paquetes más, ninguno de los cuales tu equipo escribió ni versionó a mano. Un SBOM (Software Bill of Materials, "lista de materiales de software") es el documento que hace esa raíz completamente visible: cada componente, su versión exacta, y —donde la herramienta que lo genera puede determinarlo— su licencia. Esta lección explica qué es, por qué el formato importa, y qué preguntas responde que un archivo requirements.txt escrito a mano nunca podría.

Conexión con el módulo

Esta lección es puramente conceptual — el terreno que la lección 3 necesita antes de ejecutar trivy fs de verdad sobre andes-cargo-infra/. Todo lo que aprendas aquí sobre qué campos tiene un SBOM y qué preguntas responde lo vas a ver, literal, en la salida real de esa lección.


Analogía: la lista de ingredientes de una lata de conservas

Compra una lata de conservas en cualquier supermercado y vas a encontrar, en la etiqueta, una lista de ingredientes obligatoria por ley: cada componente, en orden de proporción, a veces con su origen o su número de aditivo. Esa lista no te dice si la lata está en buen estado, ni si el contenido sabe bien, ni si va a caducar pronto — no es una promesa de calidad. Lo que sí te dice, con precisión, es exactamente qué hay adentro: si eres alérgico a un ingrediente específico, esa lista te lo confirma sin que tengas que abrir la lata y analizar el contenido tú mismo.

Un SBOM es esa misma lista, aplicada a software. No te dice si andes-cargo-infra/ es "seguro" en un sentido general —esa pregunta la responden, en parte, conftest (Módulo 4) y Trivy/Checkov aplicados a configuración (Módulo 5)—. Lo que un SBOM responde es una pregunta más estrecha y, precisamente por eso, más verificable: ¿qué componentes de software, exactamente, con qué versión, terminan corriendo dentro de este artefacto? Cuando mañana aparezca una vulnerabilidad crítica en una librería que nadie en tu equipo instaló explícitamente —una que llegó como dependencia de una dependencia—, un SBOM es el documento que te permite responder, en segundos y sin adivinar, "¿nos afecta esto, sí o no?".


Qué preguntas responde un SBOM que un requirements.txt no responde

Es tentador pensar que un archivo requirements.txt con una sola línea —boto3==1.40.76— ya es, en sí mismo, un inventario completo de dependencias. No lo es, y la brecha entre ambos es exactamente lo que un SBOM cierra.

Primera brecha: las dependencias transitivas. requirements.txt declara lo que tu equipo decidió instalar explícitamente — una sola línea, un solo paquete nombrado a mano. Pero ese paquete, al instalarse, trae consigo sus propias dependencias, que a su vez pueden traer las suyas — la cadena completa se llama el árbol de dependencias transitivas, y ningún requirements.txt escrito a mano lo expone. La lección 3 de este módulo lo va a mostrar con un número exacto y ejecutado: una sola línea declarada (boto3==1.40.76) resuelve, en la práctica, a siete paquetes reales instalados — boto3 más seis dependencias transitivas que nadie en Andes Cargo escribió en ningún archivo a mano. Un SBOM captura las siete, con su versión exacta cada una; un requirements.txt de una línea solo muestra la primera.

Segunda brecha: la licencia de cada componente. Cada paquete de software se distribuye bajo una licencia —MIT, Apache 2.0, GPL, BSD, y docenas de variantes menos comunes—, y esa licencia determina qué puede hacer legalmente una empresa con ese código: si puede usarlo en un producto comercial cerrado, si tiene que publicar el código fuente de lo que construya con él, si tiene que atribuir al autor original. requirements.txt no tiene ningún campo para esto — es, por diseño, solo una lista de nombres y versiones, sin ningún metadato legal. El formato de un SBOM sí tiene un campo estructurado para la licencia de cada componente (lo vas a ver en la lección 3), aunque —y esto importa tanto como la capacidad misma— que el campo exista en el formato no garantiza que la herramienta que genera el SBOM siempre pueda completarlo: la lección 3 documenta, con evidencia real, un caso concreto donde esa detección no fue posible en esta corrida específica, y por qué.

Tercera brecha: la trazabilidad frente a un incidente de la industria. Cuando una vulnerabilidad crítica se hace pública en un paquete ampliamente usado —el tipo de incidente que ocurre varias veces al año en el ecosistema de software abierto—, la pregunta urgente de cualquier equipo de ingeniería es: "¿estamos usando esa versión, en algún lugar de nuestro sistema, aunque sea como dependencia de una dependencia?". Sin un SBOM, responder esa pregunta exige inspeccionar manualmente cada entorno instalado — un proceso lento, propenso a error, y que no escala más allá de un puñado de proyectos. Con un SBOM generado y guardado en cada corrida de CI, la respuesta es una búsqueda de texto en un archivo JSON.


Los dos formatos que dominan la industria: SPDX y CycloneDX

Un SBOM no es un formato único — son, en la práctica, dos estándares competidores, ambos ampliamente adoptados, y esta guía usa uno de ellos por una razón concreta que vale la pena entender antes de generar el primero.

SPDX (Software Package Data Exchange) nació en el proyecto Linux Foundation con un énfasis histórico en licencias y cumplimiento legal — su origen está en la necesidad de las empresas de auditar, con precisión, bajo qué términos legales pueden redistribuir el software que usan. Es un estándar ISO (ISO/IEC 5962:2021), lo que lo hace la opción preferida en contextos regulatorios estrictos.

CycloneDX, desarrollado por OWASP (Open Worldwide Application Security Project), nació con un énfasis distinto: seguridad de aplicaciones y gestión de riesgo de cadena de suministro en tiempo real — su diseño prioriza la facilidad de generación automatizada dentro de un pipeline de CI/CD y la integración directa con herramientas de análisis de vulnerabilidades. Es el formato que Trivy soporta de forma nativa y completa, y es el que esta guía usa en la lección 3, por una razón práctica y honesta: es el formato en el que la herramienta $0 de esta guía —Trivy, ya instalada desde el Módulo 5— genera un SBOM sin ninguna conversión ni herramienta adicional.

   SPDX                                    CycloneDX
   ────                                    ─────────
   Linux Foundation                        OWASP
   Énfasis: licencias, cumplimiento legal  Énfasis: seguridad, cadena de suministro
   Estándar ISO/IEC 5962:2021              Especificación abierta, sin ISO
   Extensión típica: .spdx.json            Extensión típica: .cyclonedx.json

              ambos son SBOMs válidos — ninguno es "el correcto"
              esta guía usa CycloneDX porque es el que Trivy genera nativo

Ninguno de los dos es "el formato correcto" en abstracto — son dos estándares con énfasis distintos, y muchas organizaciones grandes terminan generando ambos, para audiencias distintas (legal/cumplimiento consume SPDX; seguridad/DevOps consume CycloneDX). Esta guía elige CycloneDX por la razón más honesta posible: es la que la herramienta $0 ya instalada produce sin fricción adicional, y el objetivo pedagógico de este módulo es que generes un SBOM real, no que compares exhaustivamente dos especificaciones.


La anatomía de un SBOM CycloneDX, antes de generarlo

Antes de ejecutar nada en la lección 3, vale la pena saber qué esperar dentro del archivo. Un documento CycloneDX válido tiene, como mínimo, esta forma:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.7",
  "serialNumber": "urn:uuid:...",
  "metadata": {
    "timestamp": "...",
    "tools": { "components": [ { "name": "trivy", "version": "0.74.0" } ] }
  },
  "components": [
    {
      "type": "library",
      "name": "boto3",
      "version": "1.40.76",
      "purl": "pkg:pypi/boto3@1.40.76"
    }
  ],
  "dependencies": [ ]
}

Cinco campos merecen atención antes de ver la salida real:

  • bomFormat/specVersion — identifican, sin ambigüedad, qué estándar y qué versión de ese estándar produjo el documento. Un SBOM CycloneDX y uno SPDX nunca se confunden entre sí porque este campo lo declara explícitamente.
  • metadata.timestamp — el momento exacto en que se generó el documento. Este campo varía en cada corrida — es el reloj real de la máquina que ejecuta trivy fs, nunca un valor fijo. La lección 3 lo marca explícitamente como variable, siguiendo la misma regla de honestidad que ya viste con las firmas de cosign más adelante en este módulo.
  • metadata.tools — qué herramienta, con qué versión exacta, generó el SBOM. Es la respuesta a "¿con qué se generó esto?", útil cuando alguien audita el documento meses después y necesita saber si una versión más nueva de la herramienta detectaría algo distinto.
  • components — la lista completa de piezas de software encontradas, cada una con su type (library, application, framework), name, version, y —el campo más importante para trazabilidad— su purl (Package URL), un identificador estandarizado (pkg:pypi/boto3@1.40.76) que apunta, sin ambigüedad, a exactamente ese paquete en exactamente ese ecosistema (PyPI, npm, Maven, y decenas de otros), en exactamente esa versión.
  • dependencies — el grafo de qué componente depende de cuál otro. Este campo es lo que distingue un SBOM real de una simple lista plana: no solo dice "estos siete paquetes existen en el proyecto", dice "boto3 depende de botocore, que depende de urllib3" — la estructura del árbol completo, no solo sus hojas.

Por qué esto no es "solo para cumplimiento legal"

Es común escuchar que un SBOM es "un trámite de cumplimiento", algo que grandes empresas reguladas producen para satisfacer a un auditor externo y que un equipo pequeño puede posponer indefinidamente. Esa percepción está desactualizada respecto al mercado real de 2026: gobiernos y grandes clientes empresariales —empezando por la orden ejecutiva de ciberseguridad de EE. UU. de 2021, que exige un SBOM para software vendido al gobierno federal— ya lo tratan como un requisito de facto para cualquier proveedor de software que quiera participar en esas cadenas de suministro. Pero incluso sin ese contexto regulatorio, el valor práctico es directo: un SBOM es lo que le permite a Andes Cargo, o a cualquier equipo, responder en minutos —no en días de inspección manual— a la pregunta "¿nos afecta la vulnerabilidad que se anunció esta mañana?". Ese es exactamente el hueco de mercado que VALIDACION.md señaló como "cero" en la competencia: no un trámite legal abstracto, sino una capacidad operativa concreta que ningún temario relevado enseña a construir.


Errores comunes

Confundir un SBOM con un escaneo de vulnerabilidades (de alcance, la confusión más frecuente). Qué pasa: alguien espera que un SBOM le diga, directamente, "este paquete tiene una vulnerabilidad crítica". Cómo detectarlo: si tu expectativa del archivo JSON de la lección 3 incluye una columna de severidad o un CVE por cada componente. Cómo corregirlo: un SBOM, por sí mismo, es un inventario — la lista de qué hay adentro, sin juicio sobre si es seguro. El escaneo de vulnerabilidades es un paso posterior y distinto, que toma ese inventario y lo cruza contra una base de datos de vulnerabilidades conocidas (exactamente lo que hace trivy fs --scanners vuln, un modo que esta lección menciona pero que la lección 3 no activa por defecto, porque el propósito de esa lección es el inventario, no el escaneo). Puedes tener un SBOM sin ningún escaneo de vulnerabilidades asociado, y puedes escanear vulnerabilidades sin generar nunca un SBOM formal — son capacidades relacionadas, no la misma cosa.

Asumir que todo SBOM incluye siempre la licencia de cada componente (de expectativa sobre la herramienta, no sobre el formato). Qué pasa: alguien lee esta lección, ve que CycloneDX tiene un campo estructurado para licencias, y asume que cualquier SBOM generado con cualquier herramienta va a tener ese campo completo para cada componente. Cómo detectarlo: si te sorprende, en la lección 3, encontrar un componente sin licencia declarada. Cómo corregirlo: que el formato tenga un campo para la licencia no significa que la herramienta, en una corrida específica, siempre pueda completarlo — la detección de licencia depende de qué metadatos estén disponibles en el entorno que se escanea (por ejemplo, si hay paquetes instalados con su metadato de licencia accesible, frente a solo un archivo de dependencias declaradas sin instalar). La lección 3 documenta, con la salida real de esta guía, un caso concreto donde esa detección no ocurrió — y explica la razón exacta, no la esconde.

Pensar que generar un SBOM una sola vez es suficiente para siempre (de mantenimiento). Qué pasa: alguien genera sbom.cyclonedx.json una vez, lo guarda, y nunca lo vuelve a generar aunque el proyecto cambie. Cómo detectarlo: si la fecha de tu SBOM es de hace meses, pero requirements.txt cambió desde entonces. Cómo corregirlo: un SBOM es una fotografía del momento exacto en que se generó — tan útil como esa fotografía sea reciente. La lección 8 de este módulo integra la generación del SBOM como parte del pipeline (no como un paso manual aislado), exactamente para que cada cambio real al proyecto produzca un SBOM actualizado, no uno que envejece en silencio.


Ejercicios

Ejercicio 1 — Explica la analogía de la lata de conservas a alguien que nunca programó. Sin usar ningún término técnico (SBOM, dependencia, paquete), explica en dos frases qué problema resuelve este documento.

Ver solución

Una respuesta completa suena, más o menos, así: "Cuando compras comida enlatada, la etiqueta te dice exactamente qué ingredientes tiene adentro, aunque tú no hayas cocinado nada — así, si eres alérgico a algo, lo sabes sin abrir la lata. Este documento hace lo mismo con un programa: te dice exactamente qué piezas de código hay adentro, incluidas las que nadie en el equipo escribió a mano, para que si una de esas piezas resulta tener un problema, lo sepas de inmediato en vez de tener que revisar todo el programa pieza por pieza."

Ejercicio 2 — Predice cuántos componentes esperarías ver en el SBOM de andes-cargo-infra/lambda/, antes de correr la lección 3. Basándote en lo que sabes de handler.py (Módulo 3 de terraform-and-iac-guide: import json, import urllib.parse, import boto3), ¿cuántas dependencias de terceros esperarías que un SBOM real encuentre, y por qué json y urllib.parse no cuentan?

Ver solución

json y urllib.parse son parte de la biblioteca estándar de Python — vienen incluidos con cualquier instalación de Python, no se instalan por separado ni tienen un número de versión independiente que un SBOM pueda rastrear como componente externo. boto3, en cambio, es una dependencia de terceros real, instalada desde PyPI, con su propio ciclo de versiones — y, como ya adelantó esta lección, resuelve a varios paquetes más cuando se instala de verdad (sus dependencias transitivas: botocore, s3transfer, jmespath, python-dateutil, urllib3, six, en la versión que la lección 3 va a instalar y escanear). Un SBOM generado correctamente encontraría, entonces, un número mayor a uno —boto3 más su árbol completo—, nunca solo la línea que un desarrollador escribió a mano.

Ejercicio 3 — Decide qué formato (SPDX o CycloneDX) elegirías para dos escenarios distintos, y justifica. Un equipo legal de una empresa grande necesita auditar, una vez al trimestre, bajo qué licencias está distribuido cada componente de un producto de software antes de firmar un contrato con un cliente empresarial. Un equipo de seguridad de la misma empresa necesita generar un inventario automatizado en cada corrida de CI para cruzarlo contra una base de datos de vulnerabilidades. ¿Qué formato usarías para cada caso?

Ver solución

Para el equipo legal, SPDX es la elección más natural — su origen y diseño priorizan precisamente la trazabilidad de licencias y el cumplimiento regulatorio, el caso de uso exacto que describe el escenario, y su estatus de estándar ISO le da peso adicional frente a un cliente empresarial o un auditor externo. Para el equipo de seguridad, CycloneDX encaja mejor — nació para integrarse en pipelines de CI/CD y cruzar contra bases de datos de vulnerabilidades de forma automatizada, exactamente el flujo descrito. En la práctica, muchas organizaciones grandes no eligen uno solo: generan ambos, cada uno para la audiencia y el propósito que mejor sirve. Ninguna de las dos elecciones es "incorrecta" en abstracto — dependen del problema concreto que cada equipo necesita resolver, no de una superioridad técnica de un formato sobre el otro.


Resumen y siguiente paso

Esta lección estableció qué es un SBOM —la lista completa y verificable de qué componentes de software terminan corriendo dentro de un artefacto, incluidas las dependencias transitivas que nadie escribió a mano— y por qué responde preguntas que ningún requirements.txt escrito a mano puede responder: el árbol completo de dependencias, la licencia de cada componente (donde la herramienta pueda detectarla), y la capacidad de responder en minutos a un incidente de seguridad de la industria. Viste los dos formatos que dominan el mercado —SPDX y CycloneDX— y por qué esta guía usa CycloneDX: es el formato que Trivy, ya instalada desde el Módulo 5, genera de forma nativa.

Antes de avanzar deberías poder: explicar la diferencia entre un SBOM y un escaneo de vulnerabilidades sin confundirlos; nombrar los cinco campos principales de un documento CycloneDX (bomFormat, metadata.timestamp, metadata.tools, components, dependencies); y anticipar que boto3, al resolverse de verdad, trae consigo varias dependencias transitivas que ninguna línea escrita a mano en requirements.txt expone por sí sola.

La lección 3 deja la teoría atrás: vas a correr trivy fs --format cyclonedx de verdad sobre andes-cargo-infra/lambda/, y a ver, en la salida literal de esta guía, exactamente cuántos componentes reales aparecen.

Recursos

  1. CycloneDX — Especificación oficial — el formato que esta guía usa, mantenido por OWASP.
  2. SPDX — Especificación oficial — el formato alternativo, mantenido por Linux Foundation, mencionado por contraste en esta lección.
  3. Trivy — SBOM — documentación oficial de la capacidad de generación de SBOM de Trivy, el motor de la lección 3.
  4. NTIA/CISA — Minimum Elements for a Software Bill of Materials — el documento de referencia del gobierno de EE. UU. que estableció los campos mínimos que un SBOM debe tener, la base regulatoria detrás de por qué esta capacidad dejó de ser opcional en muchas cadenas de suministro de software.