Mais 123% CVE comunicadas por dia em 2026 do que no ano passado.

Dependências

O que é um grafo de dependências?

Um grafo de dependências mapeia todos os pacotes de que o seu software depende e qual o pacote que trouxe cada um. Uma lista diz-lhe o que está no seu software. O grafo diz-lhe porque está lá e em que mais toca, e é essa a pergunta que tem quando surge uma vulnerabilidade.

Atualizado a

The same dependencies as a tree and as a graph As a tree, express leads to body-parser and send, and debug appears twice, once under each. As a graph, debug is a single node with an edge from body-parser and an edge from send, forming a diamond. Tree shared packages repeat express body-parser send debug debug Graph one node, two parents express body-parser send debug

Nós, arestas e caminhos

Num grafo de dependências, cada pacote é um nó e cada "depende de" é uma aresta de um pacote para outro. O seu projeto está no topo. As suas dependências diretas estão a uma aresta de distância, e as suas dependências transitivas são tudo o que está mais abaixo. O percurso do seu projeto até qualquer pacote é o caminho de dependência desse pacote, e um pacote pode ter vários.

Grafo, árvore ou lista

As mesmas dependências podem ser mostradas de três formas, e cada uma responde a uma pergunta diferente.

Vista O que mostra O que perde
Lista simples Cada pacote uma vez, com a sua versão Porque está lá cada pacote
Árvore Cada caminho a partir do seu projeto, tal como os gestores de pacotes o imprimem Os pacotes partilhados repetem-se, pelo que a árvore exagera a dimensão
Grafo Cada pacote uma vez, com uma aresta de cada pacote pai Mais difícil de ler a olho sem um visualizador

Os pacotes partilhados são a razão pela qual os grafos importam. Quando duas das suas dependências precisam do mesmo pacote, forma-se um diamante: um nó com dois pacotes pai. Corrigir uma vulnerabilidade nesse pacote implica conhecer ambos os caminhos, porque qualquer um dos pacotes pai pode fixar a versão antiga.

Para que serve um grafo de dependências

  • Encontrar o caminho da correção. Um pacote transitivo vulnerável corrige-se atualizando ou substituindo algo no seu caminho. O grafo mostra que dependência direta deve mudar.
  • Medir o raio de impacto. Quando surge um aviso de segurança, o grafo mostra quais das suas dependências diretas, serviços e produtos conduzem ao pacote afetado.
  • Rever licenças. Uma licença copyleft nas profundezas do grafo aplica-se tanto como uma no topo, e o caminho diz-lhe que dependência a introduziu.
  • Planear atualizações. Uma atualização maior de um pacote muda tudo o que está abaixo dele. O grafo mostra que parte da sua árvore se move.
  • Detetar concentração de risco. Um pacote pequeno e sem manutenção pelo qual passam muitos caminhos é um ponto único de falha.

Como obter um grafo de dependências

A partir do seu gestor de pacotes. Todos os gestores de pacotes imprimem a árvore resolvida, e a maioria consegue explicar porque está lá um determinado pacote. Dependências transitivas lista os comandos para npm, pnpm, Python, Go, Rust, Maven e Gradle.

A partir do GitHub. O grafo de dependências no separador Insights de um repositório é um resumo dos manifestos e lockfiles do repositório, mais as dependências submetidas através da dependency submission API. Nos ecossistemas que o suportam, o GitHub mostra o caminho transitivo que trouxe cada dependência, e consegue exportar o grafo como SBOM.

A partir de uma SBOM. O CycloneDX regista o grafo numa secção dependencies, em que cada componente lista aquilo de que depende. O SPDX usa relações DEPENDS_ON entre pacotes. Um grafo CycloneDX de uma parte de uma aplicação Express tem este aspeto:

"dependencies": [
  { "ref": "my-app", "dependsOn": ["express"] },
  { "ref": "express", "dependsOn": ["body-parser", "send"] },
  { "ref": "body-parser", "dependsOn": ["raw-body", "debug"] },
  { "ref": "send", "dependsOn": ["mime-types", "debug"] }
]

Aqui, debug aparece sob dois pacotes pai: um diamante. Muitas SBOM omitem as relações e listam apenas os componentes, o que mantém o inventário mas perde todos os caminhos.

Um grafo só é tão bom quanto a sua fonte

A maioria dos grafos de dependências é construída a partir de manifestos e lockfiles, pelo que mostra a árvore que o gestor de pacotes planeou. Não mostra pacotes restaurados de caches de CI, ferramentas de build instaladas por passos de configuração nem código obtido por scripts de instalação e transferências, e não consegue dizer se o build instalou exatamente o lockfile. Consulte porque é que um lockfile não é um registo do que foi distribuído.

Grafos de dependências no CRACI

O CRACI constrói o seu grafo a partir do próprio build. É um runner de GitHub Actions que regista cada pacote que cada job obtém, a qualquer profundidade da árvore e incluindo pacotes restaurados de caches de CI, numa SBOM que indica a sua própria completude.

  • Uma vista em grafo da SBOM. A vista de dependências mostra as camadas de dependências da SBOM nas vistas Pivot, Graph, Blob, Chord e Sunburst, com filtros de profundidade e gravidade.
  • Exportações com a árvore completa. As exportações em CycloneDX e SPDX incluem as dependências transitivas, cada uma com a sua licença declarada.
  • Builds afetados ao longo do tempo. Quando surge uma nova vulnerabilidade, o histórico de builds mostra que builds anteriores continham o pacote vulnerável, direto ou transitivo.

Consulte a geração de SBOM no CRACI ou marque uma demo para explorar o grafo de um dos seus próprios builds.

Grafos de dependências: perguntas frequentes

O que é um grafo de dependências?

Um grafo de dependências é um mapa de todos os pacotes de que o seu software depende, com uma seta de cada pacote para os pacotes de que precisa. Mostra não só o que está no seu software, mas também porquê: o caminho do seu código até cada dependência transitiva.

Qual é a diferença entre uma árvore de dependências e um grafo de dependências?

Uma árvore mostra cada caminho separadamente, pelo que um pacote necessário a dois pacotes pai aparece duas vezes. Um grafo mostra cada pacote uma vez, com uma aresta de cada pacote pai que precisa dele. Os gestores de pacotes imprimem árvores porque são fáceis de ler; as ferramentas que analisam o impacto trabalham sobre o grafo.

Uma SBOM contém um grafo de dependências?

Pode conter. O CycloneDX tem uma secção de dependências em que cada componente lista os componentes de que depende, e o SPDX exprime o mesmo com relações DEPENDS_ON. Muitas SBOM omitem as relações e listam apenas os componentes, o que perde os caminhos.

Como vejo o grafo de dependências de um repositório GitHub?

Abra o separador Insights do repositório e escolha Dependency graph. O GitHub constrói-o a partir dos manifestos e lockfiles do repositório, mais o que for submetido através da sua dependency submission API, e, nos ecossistemas que o suportam, mostra o caminho que trouxe cada dependência transitiva.

O que é uma dependência em diamante?

Duas das suas dependências dependem do mesmo pacote, pelo que o grafo forma um diamante. Se precisarem de versões incompatíveis desse pacote, o gestor de pacotes tem de instalar duas cópias ou falhar, e essa é uma das formas de um grafo se tornar mais difícil de gerir do que parece.

Veja o grafo do que o seu build trouxe

Execute um workflow de GitHub Actions no CRACI e explore o grafo de dependências da SBOM registada, a qualquer profundidade da árvore.

Marcar demo