Faultline: encontre a falha que ninguém encontra
Um auditor de código sem dependências para as fronteiras do seu sistema. Um comando lê o seu código atrás de chamadas externas sem timeout, retentativas sem backoff, endpoints de pagamento sem chave de idempotência, erros engolidos, SQL e shell montados por string, segredos no código, cookies sem flags e consultas que esquecem o tenant, e diz como corrigir cada um.
Instalar e rodar
Node 18 ou mais novo. Nada mais para instalar, nada em que confiar, nada sai da sua máquina.
npx github:thefgxdev/faultline . --fail-on highnpx https://codeload.github.com/thefgxdev/faultline/tar.gz/main .- uses: thefgxdev/faultline@main
with:
path: .
fail-on: highComo é uma execução
faultline · scanned 214 files in /srv/shop
CRITICAL Credential committed in source [secret-in-code]
fix: Move it to an environment variable or a secrets manager, rotate the credential now …
src/api/pay.ts:7 sk_live_51H8…
HIGH SQL built by string concatenation or interpolation [sql-string-concat]
fix: Use parameterised queries ($1, ?, named parameters) …
src/api/pay.ts:13 `SELECT * FROM orders WHERE id = ${req.body.orderId}`
MEDIUM Money or irreversible endpoint without an idempotency key [mutation-without-idempotency]
src/api/pay.ts:10 app.post('/api/pay', async (req, res) => {
MEDIUM Error caught and discarded [swallowed-error]
src/api/pay.ts:17 catch (e) {}
critical 1 · high 4 · medium 6 · low 3 · info 1Por quê
Em mais de 600 sistemas construídos, revisados ou auditados, o padrão nunca muda: a falha está numa fronteira em que alguém confiou. A chamada de rede que não tem timeout. O endpoint de pagamento que cobra duas vezes quando o cliente retenta. O catch que esconde a queda. A consulta que esquece o tenant.
Nenhum desses casos é exótico. Todos são encontrados lendo o código por onde passam dinheiro e dados. O Faultline lê esse código antes, para que a revisão humana comece nas linhas certas. É uma lanterna, não um juiz: cada achado nomeia a fronteira, mostra a evidência e diz o que fazer.
O que ele encontra (22)
Regras tiradas diretamente do código-fonte atual do projeto. Toda regra vem com a mudança que a resolve.
| Severidade | Regra | Correção |
|---|---|---|
| Segredos | ||
| crítico | Credencial commitada no código-fontesecret-in-code | Mova para variável de ambiente ou cofre de segredos, revogue a credencial agora (ela já está no histórico) e adicione um scanner de segredos no CI. |
| alto | Senha ou segredo atribuído como literalpassword-literal | Leia de process.env ou de um cofre de segredos. Um literal no código vai para o repositório, o build e o log. |
| alto | Arquivo .env presente e não ignorado pelo gitenv-file-not-ignored | Adicione .env ao .gitignore e confira se ele já não foi commitado. |
| Fronteiras | ||
| médio | Chamada externa sem timeoutfetch-without-timeout | Passe um AbortSignal (AbortSignal.timeout(ms)) ou a opção de timeout do cliente. Uma chamada sem timeout segura uma thread para sempre. |
| médio | Laço de retentativa sem backoff ou jitterretry-without-backoff | Adicione backoff exponencial com jitter e um número máximo de tentativas. Retentar na hora transforma uma falha em uma inundação causada por você. |
| info | Servidor HTTP sem limitador de taxa nas dependênciasno-rate-limit | Adicione rate limiting em login, redefinição de senha, OTP e endpoints caros, na aplicação ou na borda. |
| Erros | ||
| médio | Erro capturado e descartadoswallowed-error | Decida na fronteira: retentar, degradar ou falhar. Se ignorar for correto, registre com contexto e diga por quê em um comentário. |
| Injeção | ||
| alto | SQL montado por concatenação ou interpolação de stringsql-string-concat | Use consultas parametrizadas ($1, ?, parâmetros nomeados) ou os bindings do query builder. Nunca interpole entrada do usuário em SQL. |
| alto | Comando de shell montado a partir de variáveisshell-exec-interpolation | Use execFile ou spawn com um array de argumentos. Nenhum shell, nenhuma interpolação. |
| alto | eval ou new Function sobre entrada dinâmicaeval-usage | Remova. Use um parser, uma tabela de consulta ou um runtime isolado feito para código não confiável. |
| médio | HTML injetado a partir de uma variávelunsafe-html | Renderize texto pelo template engine ou pelo React; se HTML for necessário, sanitize com uma lista de permissões antes. |
| Autenticação | ||
| alto | Math.random usado para token, código ou senhainsecure-random-for-secret | Use crypto.randomBytes, randomUUID ou getRandomValues. Math.random é previsível. |
| médio | Cookie criado sem httpOnly, secure ou sameSitecookie-without-flags | Defina httpOnly, secure e sameSite em todo cookie de sessão ou autenticação. |
| médio | JWT verificado sem fixar os algoritmosjwt-verify-without-algorithms | Passe a lista de algoritmos aceitos na verificação. Sem isso, um token assinado com "none" ou com outro algoritmo pode ser aceito. |
| alto | CORS aceita qualquer origem com credenciaiscors-wildcard-with-credentials | Use uma lista explícita de origens. "*" com credenciais permite que qualquer site aja como o usuário logado. |
| Idempotência | ||
| médio | Endpoint de dinheiro ou irreversível sem chave de idempotênciamutation-without-idempotency | Aceite um Idempotency-Key ligado ao usuário, guarde antes do efeito colateral e devolva o resultado guardado na repetição. Duplo clique e resposta perdida são normais. |
| Isolamento de tenant | ||
| baixo | Consulta em base multi-tenant sem filtro de tenant por pertoquery-without-tenant | Filtre por tenant em toda leitura, ou imponha isso com row-level security para que um filtro esquecido devolva nada em vez de tudo. |
| Dados | ||
| baixo | SELECT * em código de aplicaçãoselect-star | Liste as colunas. SELECT * quebra quando o esquema muda e carrega dados que ninguém pediu. |
| baixo | Consulta de listagem sem limiteunbounded-list-query | Pagine. Uma listagem sem limite funciona no teste e derruba o banco no primeiro cliente grande. |
| Web | ||
| baixo | target="_blank" sem rel="noopener"blank-target-without-noopener | Adicione rel="noopener" (ou noreferrer). Sem isso a página aberta controla a página de origem. |
| Infraestrutura | ||
| baixo | Dockerfile usa :latest ou roda como rootdockerfile-latest-or-root | Fixe a versão da imagem base e adicione USER com um usuário sem privilégios. |
| Cadeia de suprimentos | ||
| médio | Nenhum lockfile commitadono-lockfile | Commite package-lock.json, pnpm-lock.yaml, yarn.lock ou bun.lock para que toda instalação seja reprodutível. |
Como ele é feito
- Zero dependênciasNode.js puro, nenhum pacote. Nada para auditar antes de auditar.
- Heurísticas, com o nome certoAs regras são expressões regulares com janelas de contexto, ajustadas para poucos falsos positivos em código real. Elas apontam fronteiras; um achado é um convite para ler, não um veredito.
- Correções, não só alarmesToda regra vem com a mudança que a resolve, em uma frase.
- Feito para o CICódigo de saída por severidade, relatório em Markdown, saída em JSON, GitHub Action.
- Testado cinco vezesTestes de fixture para cada regra, 38 testes de borda, auto-scan do repositório inteiro e varreduras de código real, em Node 18, 20 e 22 a cada push.
- Local e privadoEle lê seus arquivos e imprime um relatório. Sem rede, sem telemetria, sem conta.
Ignorando o que foi de propósito
Ignore caminhos com --ignore "glob" (repetível) ou um arquivo .faultlineignore. Silencie uma linha com // faultline-ignore, ou a linha seguinte com // faultline-ignore-next. Os silêncios ficam visíveis na revisão; esse é o ponto.
Autoria e licença
O Faultline é criado e mantido por Felipe Guedes, Engenheiro de Software e Arquiteto de Sistemas, em Toledo, Paraná, a partir da prática de auditoria descrita neste site. Primeira publicação em 25/09/2026.
Licença: AGPL-3.0-or-later. Rodar o Faultline no seu código, no trabalho ou num produto comercial, é gratuito e não cria obrigação nenhuma. Se você modificar o Faultline e distribuir, ou oferecer como serviço, precisa publicar o código modificado sob a mesma licença e manter o aviso de autoria. Empresas que precisam de modificação fechada podem licenciar comercialmente.
Perguntas frequentes
O que é o Faultline?
O Faultline é uma ferramenta de linha de comando, gratuita e open source, que audita um código-fonte atrás de falhas de fronteira: chamadas externas sem timeout, retentativas sem backoff, endpoints de dinheiro sem chave de idempotência, erros engolidos, SQL e comandos de shell montados por string, segredos commitados, cookies sem flags de segurança, CORS mal configurado e consultas que esquecem o tenant. Ele imprime cada achado com arquivo, linha, evidência e correção.
O Faultline é gratuito? Posso usar na empresa?
Sim. Rodar o Faultline em qualquer código, comercial ou não, é gratuito e não cria obrigação. A licença AGPL-3.0 só se aplica se você modificar o Faultline em si e distribuir ou oferecer como serviço: aí o código modificado precisa ser publicado sob a mesma licença. Modificações fechadas ficam disponíveis por licença comercial com o autor.
O Faultline envia meu código para algum lugar?
Não. Ele roda localmente, tem zero dependências, não faz chamadas de rede e não tem telemetria. Ele lê seus arquivos e imprime um relatório.
Qual a diferença entre Faultline, ESLint, Semgrep e Snyk?
O ESLint verifica estilo e uso da linguagem. Semgrep e Snyk são plataformas amplas, com marketplace de regras, contas e serviços. O Faultline é uma única passada pela árvore de arquivos com 22 regras opinativas sobre os lugares em que sistemas realmente falham em produção: timeouts, retentativas, idempotência, tratamento de erro, injeção, segredos, autenticação e isolamento de tenant. Foi feito para rodar antes da revisão humana e no CI, em segundos, sem instalar nada.
Como rodar o Faultline no CI?
Adicione a GitHub Action (uses: thefgxdev/faultline@main com path e fail-on) ou rode npx github:thefgxdev/faultline . --fail-on high em qualquer pipeline. O processo sai com código 1 quando um achado está na severidade escolhida ou acima, e pode gravar um relatório em Markdown e uma saída em JSON.
E os falsos positivos?
As regras são heurísticas com janelas de contexto, ajustadas em código real e testadas contra fixtures de código bom e ruim. Quando uma regra estiver errada para o seu caso, silencie a linha com // faultline-ignore ou o caminho com .faultlineignore; o silêncio fica visível na revisão de código. Reporte falsos positivos com o menor exemplo que reproduza o problema e eles viram casos de teste.
Quais linguagens o Faultline suporta?
O conjunto de regras é JavaScript e TypeScript primeiro (Node.js, Next.js, Express, Fastify, Prisma, Supabase e SQL em strings), mais Dockerfiles, arquivos .env, package.json e lockfiles. Os filtros de arquivo já aceitam Python, Go, PHP e Ruby; regras para essas fronteiras estão no roadmap.
Quem fez o Faultline?
Felipe Guedes, Engenheiro de Software e Arquiteto de Sistemas em Toledo, Paraná, depois de dez anos e mais de 600 sistemas construídos, revisados ou auditados em 19 países. A ferramenta codifica as perguntas que ele faz em toda auditoria de software.
Onde encontrar
- github.com/thefgxdev/faultlineCódigo-fonte, issues e releases no GitHub
- github.com/thefgxdev/faultline/blob/main/docs/rules.mdTodas as regras: o que dispara, quando fica calada, a correção
- github.com/thefgxdev/faultline/blob/main/AUTHORSHIP.mdDeclaração de autoria e licença
- github.com/thefgxdev/faultline/releasesReleases e histórico de mudanças
Quer a revisão humana também?
O Faultline encontra as linhas. Uma auditoria de software lê essas linhas em contexto: arquitetura, infraestrutura, segurança e privacidade, com relatório escrito ordenado por impacto.
Auditoria de software GitHub ★