
Linter baseado em regras para arquivos de configuração do cliente OpenSSH que detecta hosts duplicados, arquivos de identidade ausentes, algoritmos fracos, problemas de ordenação de curingas e configurações perigosas, com saída JSON e códigos de saída compatíveis com CI.
Verifique erros comuns no seu ~/.ssh/config.
Verifica blocos de host duplicados, arquivos de identidade ausentes, problemas de ordenação de curingas, algoritmos fracos, diretivas duplicadas e muito mais. Suporta diretivas Include com detecção de ciclos.
https://github.com/user-attachments/assets/4d995679-baed-4f20-9ba8-8f3ec94c64fd
curl -fsSL https://raw.githubusercontent.com/Noah4ever/sshconfig-lint/main/install.sh | bash
Defina VERSION=v0.1.0 ou INSTALL_DIR=~/.local/bin para sobrescrever os padrões.
brew tap Noah4ever/tap
brew install sshconfig-lint
opcional: untap Noah4ever/tap para remover o tap e manter a lista de taps limpa
cargo install sshconfig-lint
sshconfig-lint-bin - binários pré-compilados
yay -S sshconfig-lint-bin
paru -S sshconfig-lint-bin
Baixe um binário na página de releases.
# verifica o ~/.ssh/config padrão
sshconfig-lint
# verifica um arquivo específico
sshconfig-lint --config /caminho/para/config
# saída em json
sshconfig-lint --format json
# trata avisos como erros (útil em CI)
sshconfig-lint --strict
# ignora a resolução de Includes
sshconfig-lint --no-includes
linha 4: [aviso] WILDCARD_ORDER (wildcard-host-order) O host 'github.com' aparece depois de 'Host *' (linha 1); nunca será correspondido porque Host * já correspondeu (dica: mova Host * para o final do arquivo)
linha 7: [aviso] DUP_HOST (duplicate-host) bloco Host 'github.com' duplicado (primeira vez na linha 4) (dica: remova um dos blocos Host duplicados)
linha 3: [erro] MISSING_IDENTITY (identity-file-exists) IdentityFile não encontrado: ~/.ssh/id_missing (dica: verifique o caminho ou remova a diretiva)
A saída é ordenada por arquivo e número de linha, sendo determinística entre execuções (estável para diffs e snapshots em CI).
Erros são vermelhos, avisos são amarelos, informações são ciano. As cores são desabilitadas automaticamente quando stdout não é um terminal ou quando NO_COLOR está definido.
| Código | Significado |
|---|---|
| 0 | Limpo, nenhum erro encontrado |
| 1 | Pelo menos um achado do nível erro (ou aviso com --strict) |
| 2 | Arquivo de configuração não encontrado |
Cada achado possui um código estável que você pode usar para grep ou correspondência em scripts.
Os achados incluem uma dica quando possível, como "mova Host * para o final do arquivo".
Host github.com gitlab.com)Include conf.d/*.conf extra.conf)IdentityFile ~/.ssh/id # minha chave)ProxyCommand "ssh -W %h:%p bastion")cargo test # executa todos os testes
cargo test --lib # apenas testes unitários
cargo clippy # lint
cargo fmt --check # formatação
src/
main.rs CLI
lib.rs API pública (lint_file, lint_str)
model.rs Tipos da AST
lexer.rs Tokenizador
parser.rs Constrói a AST da configuração a partir dos tokens
resolve.rs Expansão de Include + detecção de ciclos
report.rs Formatadores de texto e JSON
rules/
mod.rs Trait Rule e executor
basic.rs Regras embutidas
tests/
fixtures/ Arquivos de configuração de exemplo
cli.rs Testes de integração da CLI
integration.rs Testes baseados em fixtures
Rule em src/rules/basic.rsrun_all() em src/rules/mod.rsVeja CONTRIBUTING.md para mais detalhes.
MIT
| Código | Regra | Severidade | Descrição |
|---|
DUP_HOST | duplicate-host | aviso | Dois blocos Host com o mesmo padrão |
MISSING_IDENTITY | identity-file-exists | erro | Caminho do IdentityFile não existe |
WILDCARD_ORDER | wildcard-host-order | aviso | Host * aparece antes de padrões específicos |
WEAK_ALGO | deprecated-weak-algorithms | aviso | Algoritmo fraco ou obsoleto (3des-cbc, arcfour, hmac-md5, ssh-dss, etc.) |
DUP_DIRECTIVE | duplicate-directives | aviso | Mesma diretiva repetida em um escopo (apenas o primeiro valor tem efeito) |
INSECURE_OPT | insecure-option | aviso | Configuração perigosa como StrictHostKeyChecking no ou ForwardAgent yes em Host * |
UNSAFE_CTRL_PATH | unsafe-control-path | aviso | ControlPath sem %h, %p, %r (ou %C) — conexões podem compartilhar um socket |
INCLUDE_CYCLE | include-cycle | erro | Cadeia Include circular |
INCLUDE_READ | include-read | erro | Arquivo incluído não pode ser lido |
INCLUDE_GLOB | include-glob | erro | Padrão de glob Include inválido |
INCLUDE_NO_MATCH | include-no-match | informação | Padrão Include não correspondeu a nenhum arquivo |