Arquitetura de segurança da aplicação¶
O PEART são três processos com três fronteiras de confiança, e um modelo de conteúdo feito para guardar
entrada hostil sem nunca executá-la. O relato autoritativo é o docs/security.md; esta página o resume
para quem avalia.
Três processos, três fronteiras¶
A superfície interna (peart) é onde o pentester trabalha: leitura e escrita completas no
banco, acesso à chave mestra e ao diretório de evidências. O portal (peart-portal) é onde o
cliente lê um relatório entregue: um processo separado, sem chave mestra e sem acesso ao diretório
de evidências. Ele mantém duas conexões com o mesmo arquivo de banco. A primeira, que serve toda
leitura que o cliente vê, carrega mode=ro na string de conexão, então a recusa vem do próprio
driver do SQLite e não das permissões de arquivo, que não funcionam com WAL. A segunda é de leitura
e escrita de verdade, e existe porque uma sessão não pode ser criada, tocada nem revogada por uma
conexão somente leitura; o que a estreita não é a string de conexão, e sim uma interface Go com um
conjunto fixo de métodos, de modo que os demais métodos de escrita do store ficam inalcançáveis por
ela, não apenas sem uso. Comprometer o portal não entrega a chave, a evidência original, campos
internos nem uma escrita no conteúdo do relatório: as escritas que ele alcança são as linhas da
própria sessão, os registros de auditoria dele, e a senha e o segundo fator opcional da conta que
entra.
O sidecar de renderização transforma o HTML do relatório em PDF com o WeasyPrint, e processa HTML derivado de conteúdo hostil, então é tratado como superfície de ataque. Ele roda sem saída de rede, sem banco, sem chave e sem acesso a evidência; recebe um diretório de trabalho com o HTML e os assets locais já resolvidos e devolve um PDF. Esse isolamento não é opcional, e as units de systemd o carregam.
Conteúdo hostil, nunca executado¶
Todo campo de texto é entrada hostil. O PEART armazena, exibe, exporta e imprime payloads em cinco
contextos de saída distintos sem executá-los, escapando por contexto em vez de uma vez só na esperança
de cobrir tudo. Texto rico é um dialeto de Markdown restrito, não HTML arbitrário. Planilhas
exportadas neutralizam injeção de fórmula: um campo que começa com = é prefixado e escrito como tipo
texto, então um título de achado nunca vira fórmula viva na planilha de um cliente.
O front-end impõe isso no navegador também. A Content-Security-Policy não carrega unsafe-inline nem
unsafe-eval; os componentes são Lit em light DOM; e o código do próprio projeto tem zero ocorrências
de innerHTML, unsafeHTML ou unsafeStatic. Um teste de navegador carrega a casca real da página e
reprova se a política é de fato violada no console, então a CSP sobre a qual todo o front-end se apoia
não regride despercebida.
Ingestão de evidência¶
A evidência enviada não é confiada como está. As dimensões reais da imagem são lidas do cabeçalho dela, e a imagem é decodificada e recodificada em vez de armazenada verbatim; um formato sem suporte seguro em Go puro é recodificado para PNG em vez de passar direto. O pipeline entrega ao renderizador um HTML que não pode carregar referência externa, fechando os vetores de server-side request forgery e de leitura de arquivo local no ponto em que o conteúdo hostil encontra o renderizador.
Autorização¶
O controle de acesso é imposto por escopo obrigatório em toda query, com negação por padrão. A fronteira que importa é um cliente alcançar o engajamento de outro cliente pelo portal, e ela é fechada exigindo o escopo na própria query, não por uma checagem que uma rota poderia esquecer.