Scaffolder de Aplicação Segura
Gera uma aplicação segura por design, em conformidade com ANSSI, CIS, FBI e OWASP ASVS nível 2: frontend TypeScript, backend Python, PostgreSQL endurecido.
Layout, README e UI seguem a skill project-blueprint. Regras de segurança nesta skill têm precedência sobre qualquer regra de conveniência ou UX.
Arquivos de referência (leia ao gerar o artefato correspondente)
- reference/docker-compose.yml: compose endurecido com bootstrap de segredos.
- reference/nginx.conf: proxy reverso com TLS 1.3, PQ híbrido, cabeçalhos, limites de taxa.
- reference/security-tests.md: matriz de testes de segurança obrigatória.
Quando Usar
- Iniciar, estruturar ou arquitetar uma nova aplicação ou serviço web.
- Solicitações mencionando ANSSI, CIS, FBI, OWASP, endurecimento, rootless, conformidade.
- Adicionar autenticação, autorização, upload de arquivos, auditoria, recursos administrativos, arquivos de implantação ou endpoints MCP.
Alvos de implantação: Docker e Podman rootless apenas. Não gere manifests Kubernetes, Helm ou outros orquestradores, a menos que o usuário peça explicitamente.
0. Modelo de Ameaça
- Crie
docs/security/threat-model.md(≤ 1 página): ativos, limites de confiança, atores, principais riscos (STRIDE) e o controle que mitiga cada um. Atualize-o quando um novo limite de confiança aparecer (upload, webhook, LLM, MCP).
1. Contêineres & Runtime
- Rootless: toda imagem termina com um
USERnumérico (ex.:USER 10001:10001), incluindo o servidor web (nginxinc/nginx-unprivileged, porta > 1024). - Imagens mínimas e fixadas: builds multi-estágio; o estágio de runtime é distroless ou slim sem shell, compilador ou gerenciador de pacotes; dependências de desenvolvimento excluídas. Imagens base fixadas por digest. Última versão estável do Python.
- Endurecimento:
read_only,tmpfspara caminhos graváveis,cap_drop: [ALL],no-new-privileges, perfil seccomp padrão do runtime (nuncaunconfined),pids_limit, limites de memória, healthchecks, desabilitação de core dumps (ulimits: core: 0). Apenas o proxy reverso publica portas; a rede do banco de dados éinternal: true. Nunca monte o socket Docker/Podman. - Sem sub-processos: sem
subprocess,os.system,shell=True. Reforçado por: sem shell na imagem, uma regra SAST, e um filtro seccomp em processo negandoexecve/execveatcarregado em cada worker após a inicialização (uma negação em nível de contêiner impediria o próprio entrypoint de iniciar). - Garantia de primeira execução: em um clone limpo,
docker compose up(tambémdocker-compose upepodman compose up) funciona na primeira tentativa: sem.env, sem etapa manual, sem pré-requisito além do motor de contêiner. Imagens são construídas automaticamente (build:), apenas recursos do Compose Specification suportados pelo Docker Compose v2 e podman-compose são usados, sem caminhos de host fora do repositório, portas publicadas > 1024, sem limites de CPU (indisponíveis em muitas configurações rootless de cgroup).make upé um wrapper simples para o mesmo comando. - Sem segredos codificados: Um serviço
initde uso único gera segredos em um volume nomeado (0600) consumido através de variáveis*_FILE. Segredos são lidos de arquivos, não de variáveis de ambiente, em produção. - Desconectado (air-gapped): todos JS/CSS/fontes/ícones empacotados; sem CDN, download em tempo de execução ou telemetria. Dependências vêm de um mirror interno (Nexus, Artifactory, devpi, Verdaccio) ao compilar offline.
- Pronto para Vault: uma única abstração de provedor de segredos (
filepadrão,vault/sopsem produção). - TLS interno: backend ↔ banco de dados sobre TLS; mTLS opcional entre serviços.
2. Cadeia de Suprimentos & Varredura
- Dependências travadas: commit de lockfiles;
npm ci,uv sync --frozenoupip install --require-hashes..npmrccomignore-scripts=truea menos que um pacote exija scripts de instalação (lista de permissões). - Gate de pré-compilação:
npm audit --audit-level=highepip-auditfalham a compilação em código de saída > 0. - SAST & segredos: pre-commit com
ruff,bandit/semgrep,eslint(+eslint-plugin-security),gitleaks. - Varreduras de imagens (
make scan):trivy image(CVEs + segredos + misconfig),trivy configem Dockerfiles e compose,oscap-podman(ouoscap-docker) contra o perfil CIS do SO base. - SBOM & assinatura (
make sbom): SBOM CycloneDX (Trivy ou Syft), imagens assinadas comcosign(baseado em chave para offline), SBOM anexado como atestado; a implantação verifica a assinatura. - DAST (opcional, recomendado): linha de base OWASP ZAP contra a stack em execução no CI.
- Atualizações: Renovate/Dependabot (ou uma revisão offline equivalente) em cadência fixa.
3. Frontend (TypeScript)
- Localização:
/frontendcom seu próprioDockerfile, compilado como assets estáticos servidos por Nginx sem privilégios. - Código compatível com CSP: sem
<script>inline, semeval/new Function, sem CSS-in-JS em tempo de execução injetando<style>sem nonce. Prefira CSS compilado. Trusted Types habilitados (require-trusted-types-for 'script'). - Entrada de confiança zero: esquema Zod tipado por formulário, compartilhado com tipos da API. Nunca use
dangerouslySetInnerHTML/v-htmlem dados não confiáveis; DOMPurify se rich text for inevitável. - Idempotência: o cliente API anexa uma chave
Idempotency-Key(UUIDv4) a toda POST/PUT/PATCH/DELETE, gerada uma vez por ação do usuário e reutilizada em novas tentativas. - CSRF: cabeçalho personalizado (
X-Requested-With) + token CSRF; o backend também verificaOrigin/Sec-Fetch-Site. Apenas lista de permissões CORS, nunca*com credenciais. - Redirecionamentos abertos:
next/returnUrlpós-login aceita apenas caminhos relativos começando com um único/. - Sem segredos no bundle; sem source maps em produção; sem dados sensíveis em
localStorage/sessionStorage.
4. Backend (Python) & Banco de Dados
- Validação: todo corpo, parâmetro de query, parâmetro de caminho e cabeçalho validado por Pydantic com comprimentos máximos e
extra="forbid"(previne mass assignment:role,owner_id,is_adminnunca são vinculáveis a partir da entrada). - Limites de recursos: tamanho máximo do corpo da requisição, profundidade/comprimento máximo do array JSON, tamanho máximo de página (ex.: 100), timeouts do lado do servidor. Expressões regulares em entrada do usuário são limitadas ou usam um motor de tempo linear (
re2) para evitar ReDoS. - Parsing seguro: sem
pickle,marshal,yaml.load(useyaml.safe_load),eval. XML viadefusedxml. Sem entrada do usuário em fontes de template (SSTI). Caminhos de arquivo resolvidos e verificados contra um diretório base (path traversal). - Armazenamento de idempotência:
(user_id, key) -> request_hash, status, response, TTL de 24 h. Mesma chave + mesmo hash retorna a resposta armazenada; hash diferente retorna422. Isso previne duplicatas; a proteção contra replay vem de TLS, tokens CSRF e sessões curtas. - SQL: ORM ou consultas parametrizadas apenas; identificadores dinâmicos (
ORDER BY, nomes de coluna) através de uma lista de permissões. - Criptografia em nível de coluna: PII criptografado no app com AES-256-GCM, criptografia de envelope (DEK por registro envolvido por uma chave mestre do provedor de segredos), coluna
key_versionpara rotação, índice cego HMAC-SHA256 para campos pesquisáveis. Chave mestre nunca armazenada no BD ou em backups do BD. - Endurecimento do banco de dados: PostgreSQL mínimo,
scram-sha-256, TLS, dois papéis (proprietário de migração, runtime apenas DML), sem superusuário do app, migrações Alembic,statement_timeoutno papel de runtime. - Console SQL (se houver): papel somente leitura, único
SELECT,statement_timeout, limite de linhas, configuração travada. - Criptografia & pós-quântica: AES-256-GCM em repouso é resistente a quantum. A prontidão PQ visa troca de chaves e assinaturas: TLS híbrido
X25519MLKEM768no proxy; ML-KEM/ML-DSA (FIPS 203/204) apenas onde a biblioteca os suporta. Valores aleatórios desecrets/crypto.getRandomValues. Nunca implemente primitivas criptográficas. - Requisições de saída (SSRF): qualquer URL configurável pela UI (webhooks, syslog, LLM, OIDC) é validada: apenas
https(a menos que explicitamente na lista de permissões), IP resolvido rejeitado se loopback/link-local/metadata (169.254.0.0/16,fd00:ec2::254) ou privado a menos que na lista de permissões, re-verificado após resolução DNS (DNS rebinding), sem redirecionamentos cross-host, timeouts rigorosos. - Webhooks de saída: assinados com HMAC-SHA256 (
X-Signature+ timestamp) para que receptores possam verificá-los. - Email: valores de cabeçalho com CR/LF removidos; SMTPS com verificação de certificado.
- Exportações: células CSV/XLSX começando com
=,+,-,@, tab ou CR são prefixadas com'(injeção de fórmula). - Limitação de taxa: login, redefinição de senha, verificação MFA, chaves de API, exportações, uploads e endpoints caros.
- Respostas:
Cache-Control: no-storeem respostas de API autenticadas. Mensagens de erro genéricas com umrequest_id; stack traces apenas em logs. UI OpenAPI desabilitada ou apenas para admin em produção.
5. Autorização
- Negar por padrão: toda rota declara sua permissão necessária; uma rota sem declaração falha na inicialização ou nos testes.
- RBAC com papéis mapeados para permissões (não papéis verificados diretamente no código).
- Verificações em nível de objeto (IDOR/BOLA): verificação de propriedade ou tenant na camada de repositório para toda leitura/escrita por ID. Acesso não autorizado a um objeto existente retorna
404. - Verificações em nível de função: rotas de admin sob
/api/v1/admin/*protegidas por uma única dependência, nunca apenas escondendo a UI. - Ações sensíveis (mudanças de papel, criação de chaves, exportações, exclusão de usuários) exigem reautenticação recente; aprovação de quatro olhos opcional para escalada de papel para admin.
6. Upload de Arquivos (se houver)
- Limite de tamanho no proxy e no app; lista de permissões de extensões e verificação de magic bytes.
- Armazenados fora da raiz web (ou storage de objetos), nomes de arquivo aleatórios, servidos com
Content-Disposition: attachmenteX-Content-Type-Options: nosniff. - Imagens re-codificadas (remove EXIF e polyglots); arquivos verificados quanto a bombas e path traversal; antivírus offline opcional (ClamAV).
- Uploads SVG e HTML recusados a menos que sanitizados e servidos de uma origem isolada.
7. Logging, Auditoria & Administração
- Logs estruturados: JSON, níveis DEBUG/INFO/WARN/ERROR/CRITICAL,
request_idem todos os lugares, timestamps UTC, CR/LF removidos de valores do usuário. Senhas, tokens, chaves, IDs de sessão nunca registrados. - Syslog remoto: RFC 5424 sobre TLS (RFC 5425) com buffer local limitado; host, porta, TLS, CA configuráveis pela UI de Admin. Sem contêiner rsyslog.
- Notificações de erro: SMTPS e webhooks configuráveis pela UI de Admin, validados contra SSRF, botão "Enviar teste", limitados.
- Mascaramento de PII: middleware ativado/desativado pela UI de Admin.
- Trilha de auditoria à prova de adulteração: tabela somente anexação (papel de runtime tem apenas
INSERT/SELECT), cada linha encadeada com o hash da linha anterior, encaminhada para syslog. Cobre logins, falhas, mudanças MFA, mudanças de papel, mudanças de configuração, exportações, chaves de API, acionamentos de honeytoken; registra usuário, IP, user agent, hora UTC e valores antes/depois. - Painel de administração: estatísticas de uso, erros, alertas de honeytoken, IPs bloqueados.
- Higienização agendada: desabilitar contas inativas, limpar tokens/sessões/chaves de idempotência expirados, backups criptografados diários (chave separada do backup), política de retenção e um procedimento de restauração testado (
make restore-test). - Dados pessoais (GDPR): períodos de retenção por tipo de dado, exportação e exclusão de dados do usuário, jobs de limpeza.
8. Autenticação, Identidade & Defesa Ativa
- Senhas: Argon2id (padrões argon2-cffi / RFC 9106, mínimo m=19 MiB, t=2, p=1), rehash ao login quando parâmetros mudam. Política conforme NIST SP 800-63B: ≥ 12 caracteres, máximo ≥ 64, sem regras de composição, rejeitada se estiver em uma lista de senhas violadas/comuns incluída.
- Login: resposta e temporização idênticas para usuários desconhecidos, atrasos progressivos + limitação por conta e por IP (evitar bloqueio permanente que permite DoS).
- Redefinição de senha: token aleatório de uso único armazenado hash, expiração de 30 min, mesma resposta independentemente de a conta existir ou não, todas as sessões revogadas após a redefinição.
- Sessões: do lado do servidor, cookie
__Host-session(HttpOnly; Secure; SameSite=Lax; Path=/), ID rotacionado no login e na mudança de privilégio, usuários podem listar e revogar suas sessões ativas. Sem JWT no armazenamento do navegador; se JWTs forem usados serviço a serviço: algoritmo fixado,nonerecusado,aud/iss/expverificados, tempo de vida curto. - Sessões de admin: 1 h de inatividade, 8 h absolutas, reautenticação para ações destrutivas.
- MFA: TOTP (códigos de recuperação hash, rejeição de replay do mesmo código) e WebAuthn/Passkeys. MFA obrigatório para contas de admin.
- Detecção de contexto: logins de admin de IP/dispositivo desconhecido disparam uma notificação "Novo login" e restringem direitos destrutivos até confirmação MFA.
- Admin de bootstrap: senha aleatória gerada no primeiro boot, legível uma vez via
make admin-password, redefinição forçada + cadastro MFA no primeiro login. - Conta de emergência (opcional): admin local utilizável quando SSO está inativo, desabilitada por padrão, todo uso gera um alerta crítico.
- SSO: fluxo de código OIDC + PKCE,
stateenoncevalidados, assinatura/aud/issdo token ID verificados; LDAPS ou StartTLS com verificação de certificado, valores de filtro LDAP escapados (injeção LDAP). Grupos de diretório mapeados para papéis. - Configuração SSO, duas fontes equivalentes: toda configuração OIDC e LDAP(S) (flag de ativação, URL do issuer/servidor, client ID, escopos, bind DN, base DN, filtros de usuário/grupo, bundle CA, mapeamento grupo-para-papel, aprovisionamento automático) pode ser definida ou pela UI de Admin ou por variáveis de ambiente (
BACKEND_OIDC_*,BACKEND_LDAP_*).- Segredos (
client_secret, bind password) vêm de variáveis*_FILEou do provedor de segredos, nunca valores de ambiente em texto claro em produção; na UI eles são somente gravação (••••últimos4). - Precedência: uma configuração definida por ambiente vence e é mostrada somente leitura na UI de Admin com um badge "Gerenciado por ambiente"; todo o resto é editável e armazenado criptografado no banco de dados.
- Mesma validação para ambas as fontes (esquema Pydantic compartilhado pelo carregador de ambiente e pela API de admin); configuração de ambiente inválida falha a inicialização com um erro claro, entrada inválida da UI é rejeitada antes de salvar.
- A UI de Admin tem uma ação "Testar conexão" (descoberta OIDC + busca JWKS, bind LDAP + busca de grupo de amostra) e toda mudança é auditada.
- Cada ...
- Segredos (
[truncado para tradução]