en
Faultlinefind the failure nobody finds
open source · zero dependências · AGPL-3.0

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.

Varre a pasta atual e falha em achados altos ou críticos
npx github:thefgxdev/faultline . --fail-on high
Sem git instalado
npx https://codeload.github.com/thefgxdev/faultline/tar.gz/main .
Como GitHub Action, no seu workflow
- uses: thefgxdev/faultline@main
  with:
    path: .
    fail-on: high

Como é 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 1

Por 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.

SeveridadeRegraCorreção
Segredos
críticoCredencial commitada no código-fonte
secret-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.
altoSenha ou segredo atribuído como literal
password-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.
altoArquivo .env presente e não ignorado pelo git
env-file-not-ignored
Adicione .env ao .gitignore e confira se ele já não foi commitado.
Fronteiras
médioChamada externa sem timeout
fetch-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édioLaço de retentativa sem backoff ou jitter
retry-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ê.
infoServidor HTTP sem limitador de taxa nas dependências
no-rate-limit
Adicione rate limiting em login, redefinição de senha, OTP e endpoints caros, na aplicação ou na borda.
Erros
médioErro capturado e descartado
swallowed-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
altoSQL montado por concatenação ou interpolação de string
sql-string-concat
Use consultas parametrizadas ($1, ?, parâmetros nomeados) ou os bindings do query builder. Nunca interpole entrada do usuário em SQL.
altoComando de shell montado a partir de variáveis
shell-exec-interpolation
Use execFile ou spawn com um array de argumentos. Nenhum shell, nenhuma interpolação.
altoeval ou new Function sobre entrada dinâmica
eval-usage
Remova. Use um parser, uma tabela de consulta ou um runtime isolado feito para código não confiável.
médioHTML injetado a partir de uma variável
unsafe-html
Renderize texto pelo template engine ou pelo React; se HTML for necessário, sanitize com uma lista de permissões antes.
Autenticação
altoMath.random usado para token, código ou senha
insecure-random-for-secret
Use crypto.randomBytes, randomUUID ou getRandomValues. Math.random é previsível.
médioCookie criado sem httpOnly, secure ou sameSite
cookie-without-flags
Defina httpOnly, secure e sameSite em todo cookie de sessão ou autenticação.
médioJWT verificado sem fixar os algoritmos
jwt-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.
altoCORS aceita qualquer origem com credenciais
cors-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édioEndpoint de dinheiro ou irreversível sem chave de idempotência
mutation-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
baixoConsulta em base multi-tenant sem filtro de tenant por perto
query-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
baixoSELECT * em código de aplicação
select-star
Liste as colunas. SELECT * quebra quando o esquema muda e carrega dados que ninguém pediu.
baixoConsulta de listagem sem limite
unbounded-list-query
Pagine. Uma listagem sem limite funciona no teste e derruba o banco no primeiro cliente grande.
Web
baixotarget="_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
baixoDockerfile usa :latest ou roda como root
dockerfile-latest-or-root
Fixe a versão da imagem base e adicione USER com um usuário sem privilégios.
Cadeia de suprimentos
médioNenhum lockfile commitado
no-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.

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 ★