Skip to main content

Como gerar um SBOM para aplicações JavaScript e Node.js

Escrito por
Blog Header Vuln card blog

22 de maio de 2023

0 minutos de leitura

Nota do editor: 31 de maio de 2023

Agora que o comando sbom da Snyk está disponível para todos, esta publicação foi atualizada para mostrar como usar a Snyk para gerar um SBOM conforme a especificação SPDX.

O que é SBOM?

SBOM é a sigla de lista de materiais de software, que reúne todos os pacotes npm de código aberto que fazem parte do seu projeto. Mas ela não se limita a pacotes de código aberto ou de software: também pode incluir bibliotecas de sistemas operacionais, inventário de microsserviços e muito mais.

Seus pacotes de software npm seriam representados em dois arquivos: o package.json, que contém suas dependências diretas, e um arquivo de lock, como package-lock.json ou yarn.lock, que representa toda a árvore de dependências instaladas ao compilar seus projetos JavaScript ou Node.js.

Por que é importante manter uma SBOM de uma aplicação Node.js?

O ecossistema JavaScript não é estranho a incidentes de segurança que afetam desenvolvedores. Entre os exemplos recentes estão o protestware, um tipo de malware criado para corromper dados em disco, e pacotes npm maliciosos que exploram ataques de confusão de dependências para se infiltrar nos sistemas internos das organizações.

Com a adoção generalizada de bibliotecas de código aberto e o aumento dos incidentes de segurança em repositórios de software como o npm, é essencial conseguir avaliar e identificar se uma versão específica de uma dependência é usada na sua aplicação. Além disso, esses riscos de segurança reforçam a necessidade de agir rapidamente, atualizando dependências ou substituindo-as em pouco tempo.

“Um registro formal que contém os detalhes e as relações da cadeia de suprimentos dos vários componentes usados na criação de software” — NIST (Instituto Nacional de Padrões e Tecnologia)

Como pessoa desenvolvedora, você pode usar um SBOM como inventário abrangente das dependências que compõem sua pilha tecnológica. Assim, fica mais fácil atualizar dependências desatualizadas e vulneráveis ou substituir pacotes sem correção disponível ou com licenças incompatíveis. Além disso, você pode dispensar vulnerabilidades que não se aplicam aos seus casos de uso específicos. Por fim, suas equipes de segurança e operações podem solicitar a geração de um SBOM para suas aplicações JavaScript e Node.js, devido aos requisitos governamentais de conformidade em cibersegurança e à necessidade de acompanhar a segurança da cadeia de suprimentos.

Como usar a API do Snyk para gerar um SBOM para uma aplicação Node.js

O Snyk é uma plataforma gratuita de segurança para desenvolvedores que automatiza a identificação e a correção de problemas de segurança. Ao monitorar seus projetos com o Snyk, você recebe correções de segurança no momento certo.

No momento, os recursos de SBOM estão disponíveis apenas nos planos pagos. Se você tem um desses planos, vamos começar a gerar um SBOM para uma aplicação Node.js.

Pré-requisitos:

  • Uma conta paga do Snyk.

  • Acesso à API do Snyk

  • Um projeto JavaScript ou Node.js importado para a plataforma Snyk

  • A ferramenta de linha de comando curl

Etapa 1: importe um projeto JavaScript para o Snyk

A primeira etapa é importar um projeto para a plataforma Snyk, para que todas as dependências e bibliotecas npm incluídas nele possam ser verificadas, monitoradas e analisadas.

Clique aqui para ver o passo a passo para importar um projeto (ou um vídeo rápido de 1 minuto, se preferir).

Etapa 2: prepare seu token do Snyk

Para fazer uma chamada à API da plataforma Snyk, precisamos de um token da API do Snyk com permissão para consultar o endpoint de relatórios de SBOM do projeto.

Se você usa a CLI do Snyk, uma maneira de encontrar o token da API do Snyk é executar o seguinte comando:

$ snyk config get api

No entanto, talvez esse token da API do Snyk não tenha as permissões necessárias para fazer solicitações à organização ou ao projeto. Em vez disso, recomendamos criar uma nova conta de serviço dedicada a essa tarefa, para automatizá-la a partir do CI e de outros sistemas.

Para criar uma conta de serviço, acesse as configurações da sua organização, depois contas de serviço e informe um nome para a nova conta de serviço, atribua a função Org Admin e clique no botão Create.

Configurações de contas de serviço do Snyk mostrando uma nova conta de serviço chamada “service_account_for_sbom_report”, com a função de administrador da organização e o botão Criar.

Você receberá um token de API. Salve-o em um local seguro e deixe-o à mão: em breve, vamos usá-lo para consultar a API do Snyk e gerar um SBOM.

Consulte a documentação do usuário do Snyk para saber mais sobre o gerenciamento de contas de serviço.

Etapa 3: encontre os IDs da organização e do projeto

Na mesma página de configurações, você encontrará o ID da organização. Copie-o e deixe-o à mão também:

Página de configurações da organização no Snyk, com a aba Geral e o campo ID da organização com um botão Copiar

Em seguida, vamos obter o ID do projeto JavaScript que importamos para o Snyk.

Acesse Projects, encontre o projeto para o qual você quer gerar um SBOM e clique para ver os detalhes:

Painel de segurança com projetos de análise de Dockerfile, package.json e código, mostrando quantidades de itens importados, testados e problemas encontrados.

Na página de detalhes do projeto, clique na guia Settings, no canto superior direito, e role a página para baixo para copiar o ID do projeto:

Página de configurações do projeto no Snyk, mostrando a aba Geral, a frequência diária dos testes e o campo ID do projeto.

Etapa 4: gere o SBOM com curl e a API do Snyk

Agora, você já deve ter estes dados:

  • Um token da API do Snyk

  • O ID da organização

  • O ID do projeto

Agora podemos enviar uma solicitação à API e obter o relatório SBOM. Vamos usar a ferramenta de linha de comando curl para enviar a solicitação HTTP à API do Snyk:

curl -H "Authorization: token $SNYK_TOKEN" \
"https://api.snyk.io/rest/orgs/<ORG_ID>/projects/<PROJECT_ID>/sbom?version=2023-03-20&format=cyclonedx1.4%2Bjson"

Os resultados retornados pela API estão no formato JSON e usam o padrão CycloneDX para o relatório SBOM. Observe o uso da codificação de URL no final do parâmetro de consulta da API: %2B codifica o caractere +.

Dica: você pode especificar várias ocorrências do parâmetro de consulta format para receber versões do SBOM em vários formatos.

Os dados de saída podem ser grandes demais ou ficar mal formatados no console. Para deixá-los mais organizados e fáceis de ler, podemos adicionar um pipe para jq:

curl -H "Authorization: token $SNYK_TOKEN" \
"https://api.snyk.io/rest/orgs/<ORG_ID>/projects/<PROJECT_ID>/sbom?version=2023-03-20&format=cyclonedx+json" | jq .

Agora, o relatório SBOM gerado está legível e deve ficar parecido com este exemplo, caso você tenha importado um projeto gerenciado pelo gerenciador de pacotes npm do JavaScript:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "metadata": {
    "timestamp": "2023-02-21T11:01:07Z",
    "tools": [
      {
        "vendor": "Snyk",
        "name": "Snyk Open Source"
      }
    ],
    "component": {
      "bom-ref": "1-goof@1.0.1",
      "type": "application",
      "name": "goof",
      "version": "1.0.1",
      "purl": "pkg:npm/goof@1.0.1"
    },
    "properties": [
      {
        "name": "snyk:org_id",
        "value": "<REDACTED>"
      },
      {
        "name": "snyk:project_id",
        "value": "<REDACTED>"
      }
    ]
  },
  "components": [
    {
      "bom-ref": "2-adm-zip@0.4.7",
      "type": "library",
      "name": "adm-zip",
      "version": "0.4.7",
      "purl": "pkg:npm/adm-zip@0.4.7"
    },
    {
      "bom-ref": "3-bytes@1.0.0",
      "type": "library",
      "name": "bytes",
      "version": "1.0.0",
      "purl": "pkg:npm/bytes@1.0.0"
    },

O relatório SBOM gerado é um documento CycloneDX 1.4 válido, que contém a lista de materiais de software do projeto Snyk em questão.

Ele traz metadados detalhados e também informa as dependências transitivas, destacando as bibliotecas das quais outras dependem. Por exemplo, no mesmo relatório mostrado acima:

  {
      "ref": "63-utils-merge@1.0.0"
    },
    {
      "ref": "64-serve-static@1.9.3",
      "dependsOn": [
        "34-escape-html@1.0.1",
        "53-parseurl@1.3.3",
        "62-send@0.12.3",
        "63-utils-merge@1.0.0"
      ]
    },
    {
      "ref": "65-type-is@1.6.16",
      "dependsOn": [
        "6-media-typer@0.3.0",
        "37-mime-types@2.1.23"
      ]
    },

Neste momento, o formato de saída CycloneDX inclui as seguintes informações:

  • Dependências diretas

  • Dependências transitivas e suas relações com os pacotes dos quais dependem.

  • Identificadores de Org e Project do Snyk para os quais este SBOM foi gerado.

  • O nome da aplicação ou do projeto para o qual este SBOM foi gerado, se estiver disponível no arquivo de manifesto do pacote fornecido como entrada.

Na documentação da API, você encontra mais opções de uso da API do Snyk para SBOM, como suporte à serialização em XML em vez de JSON ou à saída de documentos na especificação SPDX, padrão para listas de materiais de software.

Agora você pode automatizar a geração de SBOMs para suas dependências de código aberto. O que você vai criar em seguida? Compartilhe com a gente na comunidade DevSecOps no Discord.

Como usar a CLI do Snyk para gerar um SBOM para uma aplicação Node.js

Se você não tem acesso direto à API do Snyk, pode usar a CLI do Snyk, compatível com vários sistemas operacionais. Com ela, você pode encontrar, corrigir, monitorar e gerar relatórios em todos os produtos do Snyk, da análise estática de código à infraestrutura como código.

Vamos começar a gerar um SBOM para qualquer aplicação JavaScript gerenciada por um gerenciador de pacotes.

Pré-requisitos:

Em um diretório de projeto JavaScript que já tenha um arquivo de manifesto package.json, podemos analisá-lo para identificar todos os materiais de software que o compõem.

Vamos considerar um projeto Node.js com debug como devDependency e fastify como framework de aplicação web definido entre as dependências de produção:

{
  "name": "my-sbom-learning-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "debug": "^4.3.4"
  },
  "dependencies": {
    "fastify": "^4.13.0"
  }
}

Com apenas duas dependências diretas, qual é o custo das dependências transitivas? É aqui que a geração de um SBOM para o projeto faz a diferença, pois oferece uma visão completa das dependências. Vamos executar o seguinte comando snyk, que usa o diretório atual para encontrar um arquivo package.json compatível e analisá-lo:

snyk sbom --format=cyclonedx1.4+json

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "metadata": {
    "timestamp": "2023-02-27T08:06:35Z",
    "tools": [
      {
        "vendor": "Snyk",
        "name": "Snyk Open Source"
      }
    ],
    "component": {
      "bom-ref": "1-a@1.0.0",
      "type": "application",
      "name": "a",
      "version": "1.0.0",
      "purl": "pkg:npm/a@1.0.0"
    }
  },
  "components": [
    {
      "bom-ref": "2-fast-deep-equal@3.1.3",
      "type": "library",
      "name": "fast-deep-equal",
      "version": "3.1.3",
      "purl": "pkg:npm/fast-deep-equal@3.1.3"
    },
    {
      "bom-ref": "3-json-schema-traverse@1.0.0",
      "type": "library",
      "name": "json-schema-traverse",
      "version": "1.0.0",
      "purl": "pkg:npm/json-schema-traverse@1.0.0"
    },

A saída CycloneDX acima foi cortada em cerca de 40 linhas para evitar excesso de informação neste artigo. A lista completa de materiais de software de um conjunto tão pequeno de dependências diretas tem 749 linhas de JSON formatado.

Podemos usar jq para contar quantas dependências de código aberto este projeto tem:

snyk sbom --format=cyclonedx1.4+json | jq ".components | length"

O resultado é um total de 60 pacotes de código aberto na lista de materiais de software deste projeto.

Agora fica evidente a importância de um SBOM: ele vai muito além de atender a requisitos de conformidade ou regulamentações definidos pela equipe de segurança ou por uma determinação governamental. Como vimos, seu projeto depende de 60 pacotes de código aberto, não apenas dos 2 que você instalou diretamente. Essa é uma questão da cadeia de suprimentos de software, cujas implicações de segurança são significativas e representam riscos diretos para os consumidores.

Ao descobrir que seu projeto depende, na verdade, de 60 pacotes de código aberto, você pode se fazer algumas destas perguntas:

  1. Algum desses pacotes tem uma licença incompatível com as diretrizes e o uso definidos pela minha organização?

  2. Todos esses pacotes recebem manutenção ativa?

  3. O que acontece se uma nova vulnerabilidade for descoberta em um desses 60 pacotes?

Essas são algumas das questões relacionadas à integridade dos projetos que estamos ajudando a resolver com o Snyk Advisor, que oferece uma pontuação de integridade baseada em métricas de popularidade, manutenção, segurança e comunidade do projeto.

Página do Snyk Advisor para o pacote JavaScript datejs, exibindo uma pontuação de integridade de 53/100 e detalhes do status do pacote.

Voltando aos SBOMs, veja a seguir o uso completo do comando de linha de comando para verificar projetos:

$ snyk sbom --file=<file> --format=cyclonedx1.4+json [targetDirectory] 

Gere um SBOM na especificação SPDX

A CLI e os endpoints da API do Snyk também oferecem suporte à especificação SPDX. Basta atualizar a opção de linha de comando format para spdx2.3+json para gerar a saída de um SBOM compatível com SPDX no formato JSON. Veja como:

$ snyk sbom --format=spdx2.3+json

Isso gera uma saída semelhante à seguinte resposta JSON parcial do nosso projeto de referência Fastify, mostrado anteriormente:

{
  "spdxVersion": "SPDX-2.3",
  "dataLicense": "CC0-1.0",
  "SPDXID": "SPDXRef-DOCUMENT",
  "name": "my-sbom-learning-project@1.0.0",
  "documentNamespace": "https://snyk.io/spdx/sbom-",
  "creationInfo": {
    "licenseListVersion": "3.19",
    "creators": [
      "Tool: Snyk Open Source",
      "Organization: Snyk"
    ],
    "created": "2023-05-30T12:09:22Z"
  },
  "packages": [
    {
      "name": "my-sbom-learning-project",
      "SPDXID": "SPDXRef-1-my-sbom-learning-project-1.0.0",
      "versionInfo": "1.0.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/my-sbom-learning-project@1.0.0"
        }
      ]
    },
    {
      "name": "fastify",
      "SPDXID": "SPDXRef-2-fastify-4.17.0",
      "versionInfo": "4.17.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/fastify@4.17.0"
        }
      ]
    },
    {
      "name": "@fastify/ajv-compiler",
      "SPDXID": "SPDXRef-3-fastify-ajv-compiler-3.5.0",
      "versionInfo": "3.5.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/%40fastify/ajv-compiler@3.5.0"
        }
      ]
    },
    {
      "name": "ajv",
      "SPDXID": "SPDXRef-4-ajv-8.12.0",
      "versionInfo": "8.12.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/ajv@8.12.0"
        }
      ]
    },

O que mais você pode esperar de um SBOM?

O Snyk tem o compromisso de ajudar desenvolvedores a criar e lançar aplicações seguras, identificando código inseguro diretamente no IDE e criando solicitações de pull com correções automatizadas para repositórios de software no GitHub ou Bitbucket.

Neste artigo, destacamos as dependências de aplicações JavaScript como parte do inventário incluído em um SBOM. Mas ele também revela outros dados úteis sobre os componentes de software usados em um projeto. Essas informações adicionais podem ser essenciais não só para entender a composição de um produto de software, mas também para gerenciar os riscos de segurança, os requisitos de conformidade e as licenças. Veja alguns exemplos de dados que um SBOM pode fornecer:

  1. Detalhes dos componentes: incluem informações sobre cada componente usado no software, como o nome do pacote npm, a versão e a origem (se está no repositório npmjs ou em um repositório do GitHub).

  2. Informações sobre licenças: incluem detalhes sobre as licenças que regem cada componente usado no software, como tipo, termos e obrigações. Você talvez esteja acostumado a pacotes npm licenciados sob MIT ou Apache, mas uma dependência aninhada pode usar uma licença incompatível, como GNU GPL, e expor você a riscos jurídicos.

  3. Dados de vulnerabilidades: incluem informações sobre vulnerabilidades de segurança conhecidas publicamente e associadas aos pacotes npm usados no software, sejam elas de impacto direto ou indireto.

  4. Dados criptográficos: incluem informações sobre os componentes criptográficos usados no software, como algoritmos e tamanhos de chave. Por exemplo, se uma aplicação usa um algoritmo inseguro, como o hash MD5, é importante saber disso e tomar as medidas necessárias.

  5. Informações da compilação: incluem detalhes sobre como o software foi compilado, como o ambiente de compilação, as ferramentas usadas e as configurações de compilação.

  6. Metadados: incluem informações adicionais relevantes sobre o software, como o nome, a versão e a autoria do projeto.

Para ver um exemplo prático de como um SBOM pode ser útil para você como pessoa desenvolvedora JavaScript, confira a tabela a seguir:

Nome do componente

Versão

Tipo de licença

Dados de vulnerabilidades

Dados criptográficos

Express

4.4.0

MIT

N/A

Lodash

4.17.16

MIT

N/A

Vue

2.5.16

MIT

N/A

Axios

0.21.0

MIT

N/A

No momento da publicação deste artigo, o Snyk disponibiliza as dependências e suas relações nos seguintes formatos:

  • CycloneDX versão 1.4 em JSON

  • CycloneDX versão 1.4 em XML

  • SPDX versão 2.3 em JSON

A equipe está trabalhando para oferecer suporte a outras seções das especificações, como vulnerabilidades, licenças e muito mais.

O Snyk também permite trabalhar com SBOMs de outras maneiras:

  • A ferramenta de verificação de SBOM, um site gratuito onde você pode enviar um artefato SBOM para que o Snyk encontre vulnerabilidades nos pacotes npm.

  • seção sobre SBOM da API da Snyk

  • CLI da Snyk

  • Aprofunde-se na documentação do usuário sobre SBOM

  • O projeto de código aberto Bomber aceita arquivos no formato de especificação SBOM como entrada e gera uma lista de vulnerabilidades. Ele pode ser útil se você precisar trabalhar com componentes proprietários de fornecedores e também oferece suporte à Snyk como provedora de dados de vulnerabilidades.

Se você é desenvolvedor Java ou sua organização desenvolve aplicações baseadas em Java, confira o artigo do meu colega Brian Vermeer sobre como criar SBOMs em Java com Maven e Gradle.

Para uma introdução mais detalhada, recomendo ler o artigo da Snyk sobre lista de materiais de software (SBOM) para a segurança da cadeia de suprimentos de código aberto.

Proteja suas dependências de código aberto

As ferramentas da Snyk, desenvolvidas para quem programa, criam PRs de correção com um clique para dependências de código aberto vulneráveis e suas dependências transitivas.

Leia mais

blog feature snyk container custom base recommendations
Blog

Conheça o Evo Agentic AppSec: segurança que acompanha o ritmo do desenvolvimento com IA

O desenvolvimento impulsionado por IA está avançando mais rápido do que os fluxos de trabalho de segurança tradicionais. O AppSec agentivo da Snyk usa agentes de segurança para encontrar, corrigir e verificar vulnerabilidades continuamente, enquanto as pessoas definem os critérios.

blog feature ai violet
Blog

VulnBump: agentes de IA conseguem corrigir dependências vulneráveis sem quebrar o build?

O VulnBump testa agentes de IA em 307 atualizações reais de dependências. Uma correção só é considerada válida se eliminar a vulnerabilidade e mantiver o build e os testes funcionando.

Blog

Modelos de ponta encontraram as vulnerabilidades. Só o atacante encontrou as cadeias.

A análise estática encontrou as falhas, mas só os testes de ataque em aplicações ativas provaram como elas poderiam ser encadeadas para causar invasões. Uma comparação entre Evo COS, Claude Security e Claude Code Security.