O hook jwt sinaliza verificações de JWT sem algoritmo fixado, a brecha de algorithm confusion em que o verificador confia no próprio cabeçalho alg do token, e verificações desativadas por completo. Ele reconhece a linguagem e lê cada arquivo pela biblioteca de JWT dela, e é o engine determinístico por trás da especialização federation, que você mesmo pode executar no modo scan ou check.
Como executar
- Varrer o código
- Verificar uma chamada
npx lagune read jwt # scans the whole project
npx lagune read jwt --dir src # scans a directory
npx lagune read jwt --file auth.ts # scans a single file
npx lagune read jwt --lang javascript --pattern 'jwt.verify(token, secret)' # => unpinned
npx lagune read jwt --lang python --pattern 'jwt.decode(t, k, options={"verify_signature": False})' # => unpinned
npx lagune read jwt --lang python --pattern 'jwt.decode(t, k, algorithms=["HS256"])' # => safe
Cada linha em Unpinned JWT verification found é uma chamada de verificação que não define uma allowlist de algorithms (quando a biblioteca precisa de uma), aceita uma insegura (none, ou um algoritmo assimétrico misturado com HMAC) ou desativa de vez a checagem da assinatura, e por isso confia no próprio alg do token. É uma exposição confirmada, então o hook termina com código de saída diferente de zero. Uma execução sem achados imprime no unpinned JWT verification found.
Como ler o veredito
| Veredito | Significado |
|---|---|
unpinned | Uma chamada de verificação sem allowlist de algoritmos (quando é necessária), com uma allowlist insegura ou com a verificação desativada. |
safe | Uma chamada de verificação que fixa uma allowlist de algoritmos sólida, ou cuja biblioteca a fixa implicitamente. |
invalid | O trecho não contém nenhuma chamada de verificação reconhecível para julgar. |
Opções da CLI
| Opção | Valor | Descrição |
|---|---|---|
--pattern | um trecho de código | Verifica uma chamada. Repita para verificar várias, com um veredito por linha. |
--lang | uma linguagem | Obrigatória com --pattern: javascript, python, go, java, kotlin, php, ruby, rust ou csharp. |
--dir | um diretório | Limita a varredura a um diretório. Pode ser repetida e combinada com --file. |
--file | um arquivo | Limita a varredura a um único arquivo. Pode ser repetida e combinada com --dir. |
Sem nenhuma opção, ele varre o projeto inteiro. --pattern exige --lang e não pode ser combinado com --dir nem com --file.
Linguagens suportadas
A varredura lê estas bibliotecas, identificadas pela extensão do arquivo. Como algumas fixam o algoritmo implicitamente (a falta de uma lista explícita é segura), a regra "sem allowlist ⇒ unpinned" só vale onde a biblioteca espera uma lista explícita, então uma chamada configurada corretamente nunca é sinalizada.
| Linguagem | Biblioteca | Sinaliza a falta de allowlist como unpinned? | Sempre sinaliza |
|---|---|---|---|
| JavaScript / TypeScript | jsonwebtoken, jose | Sim | none, mistura de assimétrico com HMAC |
| Python | PyJWT, python-jose | Sim (o PyJWT exige, o python-jose usa algorithms=None por padrão) | none, verify_signature: False |
| Go | golang-jwt | Sim (sem WithValidMethods) | none, ParseUnverified |
| Ruby | ruby-jwt | Sim | none, verify = false |
| Java / Kotlin | jjwt, nimbus | Não (derivado da chave) | none, um parser sem assinatura ou unsecured |
| PHP | firebase/php-jwt | Não (a Key carrega o alg) | none |
| Rust | jsonwebtoken | Não (a Validation exige um) | none, insecure_disable_signature_validation |
| C# | Microsoft.IdentityModel | Não (parâmetros em várias linhas) | none, RequireSignedTokens = false |
O hook decide apenas a fixação do algoritmo: as verificações de claims, de chaves e do fluxo são julgamentos que a especialização federation continua cobrindo.
Perguntas frequentes
Um verificador que lê o algoritmo do cabeçalho do token permite que um atacante troque RS256 por HS256 e assine com a chave pública. Fixar no código uma allowlist de algoritmos sólida impede isso, e o hook jwt sinaliza uma chamada de verificação que define none ou uma allowlist insegura.
