Segurança

Segurança

SSH-Frontière é um componente de segurança. A sua razão de ser é restringir o que as conexões SSH de entrada podem fazer. Esta página documenta o modelo de segurança, o que foi implementado e o que não é garantido.

Modelo de segurança

Princípio fundamental: deny by default

Nada é executado sem estar explicitamente configurado. Se um comando não estiver na whitelist TOML, é rejeitado. Não existe modo permissivo, não existe fallback para um shell.

Três camadas de defesa em profundidade

CamadaMecanismoProteção
1command= + restrict no authorized_keysForça o nível de acesso, bloqueia forwarding/PTY
2SSH-Frontière (login shell)Valida o comando contra a whitelist TOML
3sudo whitelist nos sudoersRestringe os comandos de sistema privilegiados

Mesmo que um atacante comprometa uma chave SSH (camada 1), só pode executar os comandos autorizados na whitelist TOML (camada 2). Mesmo que contorne a camada 2, só pode elevar os seus privilégios para os comandos autorizados nos sudoers (camada 3).

Parser gramatical, não lista negra

SSH-Frontière não é um shell. A segurança não se baseia numa filtragem de caracteres (sem lista negra de |, ;, &), mas num parser gramatical.

A gramática esperada é domínio ação [key=value ...]. Tudo o que não respeita esta estrutura é rejeitado. Os caracteres especiais entre aspas são conteúdo de argumento, não sintaxe — são válidos.

std::process::Command executa diretamente, sem passar por um shell intermédio. A injeção de comandos é estruturalmente impossível.

Determinismo face aos agentes IA

Este funcionamento é determinístico: um dado comando produz sempre o mesmo resultado de validação, independentemente do contexto. É uma propriedade essencial quando se trabalha com agentes de IA, cuja natureza é justamente o indeterminismo — um modelo pode ser enviesado, ou a cadeia de produção do agente pode estar corrompida, visando os shells para recuperar informações adicionais ou exfiltrar segredos. Com SSH-Frontière, um agente comprometido não pode contornar a whitelist, não pode injetar comandos num shell, e não pode aceder a recursos não configurados. É estruturalmente impossível.

O que foi implementado

Linguagem Rust

SSH-Frontière é escrito em Rust, o que elimina as classes de vulnerabilidades mais comuns em programas de sistema:

399 testes cargo + 72 cenários E2E SSH

O projeto é coberto por 399 testes cargo e 72 cenários E2E SSH adicionais:

TipoNúmeroDescrição
Testes unitários~340Cada módulo testa independentemente (10 ficheiros *_tests.rs)
Testes de integração50Cenários stdio completos (execução do binário)
Testes de conformidade1 (6 cenários)Validação do contrato de interface JSON (ADR 0003)
Testes proptest8Testes de propriedades (fuzzing guiado por restrições)
Total cargo399
Cenários E2E SSH72Docker Compose com servidor SSH real
Harnesses cargo-fuzz9Fuzzing não guiado (mutações aleatórias)

Os testes E2E SSH cobrem o protocolo completo, a autenticação, as sessões, a segurança, a robustez e o logging. São executados num ambiente Docker Compose com um servidor SSH real.

Auditoria das dependências

Controlo de acesso RBAC

Três níveis de confiança hierárquicos:

NívelUtilizaçãoExemplos
readApenas consultahealthcheck, status, list
opsOperações correntesbackup, deploy, restart
adminTodas as açõesconfiguração, dados sensíveis

Cada ação tem um nível exigido. Cada conexão SSH tem um nível efetivo (via --level no authorized_keys ou via autenticação por token).

Tags de visibilidade

Em complemento ao RBAC vertical, tags permitem uma filtragem horizontal: um token com o tag forgejo só vê as ações marcadas com forgejo, mesmo que tenha o nível ops.

Autenticação por token

Dois modos de autenticação:

Proteções adicionais

O que não é garantido

Nenhum software é perfeito. Eis as limitações conhecidas e documentadas:

Contador XOR 8 bits

A implementação criptográfica utiliza um contador XOR com um keystream limitado a 8192 bytes. É suficiente para o uso atual (proofs SHA-256 de 64 caracteres), mas não foi concebido para cifrar grandes volumes.

Fuga de comprimento na comparação

A comparação em tempo constante pode revelar o comprimento dos valores comparados. Na prática, os proofs SHA-256 têm sempre 64 caracteres, o que torna esta fuga negligenciável.

Rate limiting por conexão

O contador de tentativas de autenticação é local a cada conexão SSH. Um atacante pode abrir N conexões e ter N x max_auth_failures tentativas. Recomendação: complementar com fail2ban, sshd MaxAuthTries, ou regras iptables.

Reportar uma vulnerabilidade

Não reporte vulnerabilidades através das issues públicas. Contacte diretamente o mantenedor para uma divulgação responsável. O processo está descrito no guia de contribuição.

Dependências

SSH-Frontière tem uma política estrita de dependências mínimas. Cada crate externa é avaliada segundo uma matriz ponderada (licença, governação, comunidade, tamanho, dependências transitivas).

CrateVersãoUtilizaçãoJustificação
serde1.xSerialização/desserializaçãoStandard de facto Rust, necessário para JSON e TOML
serde_json1.xRespostas JSONFormato de saída do protocolo
toml0.8.xCarregamento da configuraçãoFormato padrão Rust para configuração

Dependência de desenvolvimento: proptest (testes de propriedades apenas, não incluída no binário final).

Fontes autorizadas: crates.io apenas. Nenhum repositório git externo autorizado. Política verificada por cargo deny.