SAST vs SCA se resume a uma pergunta: de quem é o código que você está verificando? O SAST (static application security testing) analisa o código que sua equipe escreve. O SCA (software composition analysis) analisa o código open source que você importa. Os dois são estáticos, rodam cedo no pipeline e aparecem nos mesmos dashboards, por isso tanta gente confunde. Mas eles encontram classes de problemas completamente diferentes, e nenhum consegue fazer o trabalho do outro.
Neste guia comparamos SAST e SCA na prática: o que cada um encontra, onde se sobrepõem, por que alcançabilidade e lockfiles definem o quanto o SCA é útil, o que é risco de licenças e como rodar os dois sem afogar sua equipe em alertas.
O que o SAST faz
O SAST lê o seu código fonte e monta um modelo de como os dados circulam. Ele segue o input não confiável (parâmetros, headers, payloads de mensagens) até operações perigosas (queries SQL, comandos de shell, renderização de templates, caminhos de arquivo) e reporta o caminho vulnerável com arquivo e linha. O SAST moderno baseado em IA também raciocina sobre lógica que regras não conseguem expressar, como um handler que esquece de verificar de quem é um registro. No nosso guia de ferramentas SAST explicamos a diferença entre a abordagem por regras e o AI SAST.
Achados típicos de SAST: SQL injection, command injection, sinks de XSS, path traversal, desserialização insegura, SSRF, credenciais hardcoded, criptografia fraca e controle de acesso quebrado nos seus próprios handlers.
O que o SCA faz
O SCA monta um inventário das suas dependências a partir de manifestos e lockfiles (package-lock.json, Gemfile.lock, poetry.lock, go.sum etc.), incluindo as dependências transitivas que você nunca escolheu diretamente. Depois cruza cada pacote e versão com bases de vulnerabilidades como OSV, GitHub Advisory Database e NVD, e informa qual versão corrige o problema. Muitas ferramentas também reportam licenças. Esse mesmo inventário pode ser exportado como um SBOM.
Achados típicos de SCA: um CVE conhecido em uma versão de biblioteca que você entrega, um pacote abandonado, uma dependência com uma licença que conflita com a forma como você distribui o produto.
Tabela comparativa: SAST vs SCA
| Dimensão | SAST | SCA |
|---|---|---|
| O que analisa | O código que sua equipe escreveu | Os pacotes de terceiros dos quais você depende |
| Input | Arquivos fonte | Manifestos e lockfiles |
| O que encontra | Vulnerabilidades novas e desconhecidas na sua lógica | Vulnerabilidades conhecidas e publicadas (CVEs) e problemas de licença |
| Fonte de conhecimento | Regras, modelos de fluxo de dados ou raciocínio com IA sobre o seu código | Bases de vulnerabilidades (OSV, GitHub Advisories, NVD) |
| Correção típica | Mudar o seu código | Atualizar para uma versão corrigida ou trocar o pacote |
| Localização | Arquivo e linha | Pacote, versão e caminho de dependências |
| Principal fonte de ruído | Achados que na prática não são exploráveis | CVEs em código que você nunca chama |
| Quando surgem achados novos | Quando o código muda | Quando o código muda, e também quando sai um CVE novo para um pacote que você já usa |
Essa última linha pesa mais do que parece. Os resultados do SAST só mudam quando o seu código muda. Os do SCA podem mudar de um dia para o outro sem nenhum commit, porque alguém publicou um advisory de uma biblioteca que você usa há dois anos. O SCA precisa rodar continuamente, não só nos pull requests.
O que cada um deixa passar
Um bug que o SCA nunca vai ver
// invoices.js: seu código, sem nenhuma dependência vulnerável
app.get('/api/invoices/:id', requireLogin, async (req, res) => {
const invoice = await Invoice.findById(req.params.id);
res.json(invoice); // faltando: invoice.ownerId === req.user.id
});Todos os pacotes podem estar atualizados. A vulnerabilidade (um IDOR, parte do controle de acesso quebrado) vive na sua lógica. Só a análise do seu próprio código, seja SAST, code review ou testes, consegue encontrá-la.
Um bug que o SAST normalmente não sinaliza
// package.json
"dependencies": {
"lodash": "4.17.20"
}As versões do lodash anteriores à 4.17.21 são afetadas pelo CVE-2021-23337, uma command injection através da função template, com severidade alta. Seu código pode parecer totalmente normal; o problema é a versão que você fixou. Ferramentas SAST em geral não cruzam o conteúdo de node_modules com advisories. O SCA faz o match de [email protected] com o advisory e diz para atualizar para a 4.17.21.
Onde SAST e SCA se sobrepõem
A fronteira não é tão limpa, e é das zonas cinzentas que saem os incidentes:
- Uso inseguro de uma biblioteca segura. O PyYAML não é vulnerável, mas
yaml.load(data, Loader=yaml.Loader)sobre input do usuário é. O SCA vê um pacote saudável; o SAST vê a chamada perigosa. É assim que nascem muitas vulnerabilidades de execução remota de código. - Código vendorizado ou copiado. Uma biblioteca copiada em
vendor/ou colada de um snippet não aparece em nenhum lockfile, então o SCA pode perdê-la. O SAST a escaneia como se fosse sua, e agora ela é. - Alcançabilidade. Decidir se um CVE importa exige os dois: o SCA diz qual função é vulnerável e a análise de código diz se você a chama.
- Configuração e supply chain. Workflows de CI, Dockerfiles, imagens base e Terraform não são nem "lógica da sua app" nem "um pacote", mas fazem parte do que você entrega. Um bom programa cobre isso também, junto com um secret scanner para chaves no histórico do git.
Reachability: a diferença entre 400 alertas e 12
Uma app JavaScript típica traz centenas de pacotes transitivos, e o SCA sobre eles costuma devolver uma lista longa. Muitos desses CVEs estão em funções que o seu código nunca chama, ou em tooling de desenvolvimento que nunca roda em produção. Tratar todos como urgentes é o jeito mais rápido de ensinar a equipe a ignorar o SCA.
A análise de alcançabilidade pergunta: existe algum caminho do seu código até a função vulnerável? Se o advisory do lodash é sobre _.template e você só usa _.get, o achado é real mas de baixa prioridade. Se o seu handler passa input do usuário para _.template, ele vai para o topo da lista. Nem toda ferramenta faz reachability e nenhuma é perfeita (imports dinâmicos e reflexão deixam o call graph incompleto), mas mesmo uma versão aproximada, somada a "é uma dependência de produção?", reduz muito o ruído.
Lockfiles: o SCA é tão bom quanto o seu input
Se o seu repositório só tem "express": "^4.18.0" em um manifesto, a ferramenta de SCA precisa adivinhar qual versão você roda de verdade. Lockfiles eliminam o chute porque registram a versão exata resolvida de cada dependência direta e transitiva.
- Faça commit dos lockfiles (
package-lock.json,yarn.lock,pnpm-lock.yaml,Gemfile.lock,poetry.lock,Cargo.lock,go.sum). - Instale a partir deles no CI (
npm ci,bundle install --frozene equivalentes) para que o que você escaneia seja o que você builda. - Atenção a múltiplos lockfiles em monorepos: cada serviço pode resolver versões diferentes.
Risco de licenças
Segurança não é a única coisa que o SCA encontra. Toda dependência vem com uma licença, e algumas impõem obrigações. As permissivas como MIT, BSD ou Apache 2.0 pedem basicamente atribuição. As copyleft como GPL ou AGPL podem exigir que você publique código fonte em certas condições, e a AGPL estende isso a software oferecido pela rede. Se uma obrigação se aplica ou não depende de como você usa e distribui o código, então trate os achados de licença como insumo para uma revisão jurídica, não como veredito. O que importa para a engenharia é ter o inventário para conseguir responder a pergunta.
Por que você precisa dos dois
Pense na sua aplicação como duas metades. O SAST cobre a metade que você escreveu, onde nascem os bugs novos e desconhecidos. O SCA cobre a metade que você importou, onde se acumulam com o tempo os bugs conhecidos e publicados. Sem SAST, sua lógica de negócio fica sem revisão. Sem SCA, você fica cego para o próximo Log4Shell. Um setup prático:
- Em cada pull request: SAST no código alterado e SCA nos manifestos e lockfiles alterados, com achados ordenados por explorabilidade.
- Continuamente: cruzar de novo as dependências existentes com advisories novos, porque CVEs aparecem sem commits.
- Em uma frequência fixa: um scan completo do repositório, incluindo segredos no histórico e configuração de infraestrutura.
- Periodicamente: testes dinâmicos e pentests para o que a análise estática não vê. Nosso guia SAST e DAST cobre essa camada.
Esse é o núcleo prático de DevSecOps: verificações baratas e precisas cedo, verificações caras onde só elas ajudam.
Como o Nurbak faz os dois
O Nurbak roda SAST e SCA no mesmo scan. Você conecta o GitHub e escolhe um repositório. O próprio modelo de IA self-hosted analisa o seu código (a análise não envia seu código para a OpenAI nem para a Anthropic) e reporta vulnerabilidades exploráveis com arquivo e linha. Na mesma passada ele verifica suas dependências contra CVEs conhecidos via OSV e informa a versão corrigida para atualizar, e sinaliza configurações inseguras de GitHub Actions, Docker, Terraform e Kubernetes e segredos no histórico do git. Os resultados chegam como um score de 0 a 100 com explicações em linguagem simples, e para um achado que você decidir corrigir ele pode abrir um Pull Request com a correção mais um teste de regressão de segurança (a correção usa o Claude, com o seu consentimento explícito). O scan gratuito mostra completos os 3 achados mais importantes; os planos começam em USD 79/mês. Comece pela página de software composition analysis.
Como escolher ferramentas
- Cobertura do seu stack: linguagens para o SAST, ecossistemas de pacotes e formatos de lockfile para o SCA.
- Versões corrigidas, não só IDs de CVE: um achado de SCA sem caminho de atualização é lição de casa, não ajuda.
- Priorização: explorabilidade, alcançabilidade, dependência de produção vs de desenvolvimento.
- Fluxo do desenvolvedor: resultados nos pull requests, explicações claras, correções sugeridas.
- Tratamento de dados: onde o seu código é processado, principalmente em análise baseada em IA.
Conclusão
SAST vs SCA não é uma escolha. O SAST encontra os bugs que você escreve; o SCA encontra os bugs que você importa. Eles se sobrepõem nas bordas (como você chama as bibliotecas, reachability, código vendorizado), e é justamente por essa sobreposição que rodar os dois juntos rende mais do que qualquer um sozinho. Se você já tem um, adicione o outro. Um bom primeiro passo é verificar o seu repositório com software composition analysis e ver quantos CVEs conhecidos estão hoje no seu lockfile.
