
Faça uma verificação cruzada das visualizações da sua superfície de ataque e encontre os endpoints que não conseguem corroborar uns com os outros.
Faça a verificação cruzada das visões da sua superfície de ataque e encontre os endpoints que não conseguem corroborar uns aos outros.
Um endpoint deveria conseguir justificar a própria existência. Ele está no código, então um contrato deveria descrevê-lo. Ele está no contrato, então algo deveria implementá-lo. Ele recebe tráfego real, então é melhor que exista em algum lugar. Quando uma visão conhece um endpoint e as outras não, essa lacuna é o achado.
alibi executa o OWASP noir, lê seu JSON e compara as visões entre si.
O Noir já lê cinco visões independentes da mesma superfície:
| Visão | Lida de |
|---|---|
| code | mais de 200 analisadores em 33 linguagens |
| doc | OpenAPI, RAML, WSDL, GraphQL SDL, AsyncAPI, gRPC, Smithy, TypeSpec, OData, OpenRPC |
| traffic | HAR, mitmproxy, Burp, Caido, ZAP, Postman, Insomnia, Bruno, .http |
| gateway | nginx, Apache, Envoy, Kong, Traefik, APISIX, Caddy, Istio, Kubernetes Ingress e Gateway API |
| infra | Terraform, CloudFormation, CDK, Serverless, Vercel, Netlify, Wrangler, Azure Functions, Kamal |
O que ele não faz é compará-las. Esse é todo o trabalho aqui, e não exige nenhuma mudança no noir — o alibi o executa uma vez por visão e junta os resultados.
A parte por visão importa. O Noir deduplica por (method, url) entre todos os
analisadores, então uma rota Flask e um caminho OpenAPI escritos de forma idêntica colapsam em
um único endpoint carregando uma única tecnologia. Isso é correto para uma ferramenta de descoberta — é
um endpoint — mas apaga a corroboração que esta ferramenta foi feita para medir,
e apaga na pior direção possível: quanto melhor duas visões concordam,
mais delas desaparecem. O Casdoor é escaneado como 372 endpoints de código e 9 documentados;
escaneie apenas seu diretório swagger/ e a especificação terá 235.
--only-techs restringe o conjunto de detectores, então um scan por visão mantém cada uma
inteira. Qual tecnologia responde por qual visão é o views.yml; quais
tecnologias existem é o que noir list techs reportar.
O alibi não analisa nenhum formato de API por conta própria. Sua única entrada é o JSON do noir.
Requer o noir 1.0.0 ou mais recente no
PATH -- essa é a versão em que noir list techs se tornou um subcomando, e
esse catálogo é o que atribui cada tecnologia a uma visão. O desenvolvimento acompanha a
versão atual do noir. Um binário mais antigo é recusado pelo nome em vez de ser deixado
falhar na sua primeira leitura de catálogo.
$ uv tool install noir-alibi # or: pipx install noir-alibi
$ alibi scan ./my-service
$ alibi scan # the working directory
$ alibi scan ./service ./contracts ./prod.har # or wherever the views live
Todo caminho é uma fonte, escaneada uma vez por visão. Aponte para o que você tiver — uma árvore de código, um diretório de especificação, um único arquivo de captura — e as visões que estiverem faltando desativam suas regras em vez de inundar o relatório.
alibi · 1 source · 377 endpoints
code 372 doc 235
230 corroborated -- vouched for by more than one view
19 endpoints nearly matched another view -- these may be matching failures, not real gaps
SHADOW Shadow API -- Implemented, but no contract describes it
134 findings · 4 critical, 57 high, 62 medium, 11 low
critical POST /api/upload-groups router.go:87
upload paths carry more consequence than reads
critical POST /api/upload-permissions router.go:208
...
... and 122 more (SHADOW in full: -f json)
TWO SURFACES?
The doc view is 97% under /api, and 37 of these findings are outside it.
If that is a separate surface the contract never covered, narrow the scan:
alibi scan <paths> --ignore '^/(?!api(/|$))'
If it is the same surface left undocumented, they are the findings that matter most.
Os grupos param em doze — a ordenação é do pior para o melhor, então a cauda é a parte menos
informativa, e -f json tem tudo.
Flags para o noir vão depois de um -- isolado ou através de --noir-arg. Filtros como
--exclude-path são permitidos; flags que substituiriam o contrato JSON ou
colapsariam os scans por visão do alibi (--format, --diff-*, --only-techs, …)
são recusadas com status de saída 2.
- run: alibi scan . ./contracts -f sarif > alibi.sarif
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: alibi.sarif }
O relatório diz que as visões discordam; --endpoints diz o que cada uma delas
continha.
$ alibi scan ./repo -f json --endpoints
Cada visão recebe uma lista: a chave, quais visões a corroboraram, as tecnologias por trás dela, os arquivos, e a grafia antes da normalização — que é onde a diferença sempre está quando duas linhas deveriam ter casado e não casaram. É três a quatro vezes o resto do payload, então é uma flag em vez do padrão.
Ou faça o gate diretamente: alibi scan . ./contracts --fail-on high sai com código diferente de zero quando
um achado atinge essa severidade. Um scan que o noir não conseguiu ler por completo reporta
executionSuccessful: false, então uma execução degradada não passa como uma limpa.
O Noir mantém a sintaxe de rota de cada framework em vez de inventar uma comum, então o mesmo endpoint chega escrito de várias formas:
python_flask /api/users/<int:user_id>
aiohttp /users/{id}
java_spring /api/catalog/{id}
oas3 /v1/pets/{petId}
rails /posts/:id
nginx /admin/.*
A regra que torna esses comparáveis: o nome de um parâmetro de caminho não faz parte da
sua identidade. {petId} e <int:user_id> descrevem o mesmo slot; só importam
sua posição e se ele abrange um /. Os nomes são mantidos como evidência e
reportados, mas nunca chegam à chave.
Os achados dizem como a correspondência foi feita:
| Grau | Significado |
|---|---|
G1 | as grafias já concordavam |
G2 | concordam depois que a sintaxe de parâmetro é normalizada |
G0 | apenas uma visão o tem — nada foi correspondido |
Uma ferramenta como esta morre por reportar centenas de achados na primeira execução, ou por reportar progresso que ninguém fez. Seis coisas fazem frente:
As regras não disparam sem ambas as visões. Escaneie um código sem contratos em lugar nenhum e todo endpoint tecnicamente se qualifica como uma shadow API não documentada. Esses achados não dizem nada além de que você não forneceu nenhuma documentação, então uma regra só roda quando toda visão sobre a qual ela raciocina estava de fato no scan. O relatório nomeia as regras que ficaram de fora.
Quase-acertos são reportados como dúvida, não como achados. "No código, não na documentação" é indistinguível de "em ambos, mas o alibi falhou em alinhá-los". Então um endpoint que cai em uma visão é verificado contra as outras em busca de um quase-acerto — mesmo caminho com um verbo diferente, ou um segmento de distância onde um lado tem um parâmetro e o outro um literal. Achados carregando um quase-acerto são rebaixados e sinalizados para revisão. Essa contagem fica ao lado dos totais, porque cada achado é tão confiável quanto é pequeno.