Ir para o conteúdo

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.