Regras de Segurança
Regras de segurança base para serviços HTTP Node.js que lidam com entradas não confiáveis, segredos e requisições de saída.
Receita
Cartão de referência rápida - pronto para copiar e colar.
import { z } from "zod";
const CreateUserSchema = z.object({
email: z.string().email(),
name: z.string().min(1).max(120),
});
app.post("/users", (req, res) => {
const body = CreateUserSchema.safeParse(req.body);
if (!body.success) return res.status(400).json({ error: body.error.flatten() });
// ...
});Quando usar isso:
- Todas as rotas que aceitam JSON, parâmetros de consulta ou cabeçalhos.
- Serviços que buscam URLs fornecidas pelo usuário.
- Qualquer código que toque em chaves de API ou credenciais de banco de dados.
Exemplo de Trabalho
// src/config/env.ts
import { z } from "zod";
const EnvSchema = z.object({
DATABASE_URL: z.string().url(),
JWT_SECRET: z.string().min(32),
PORT: z.coerce.number().default(3000),
});
export const env = EnvSchema.parse(process.env);// src/security/ssrf.ts
import { lookup } from "node:dns/promises";
const BLOCKED = [/^127\./, /^10\./, /^192\.168\./, /^169\.254\./, /^0\./];
export async function assertSafeUrl(raw: string) {
const url = new URL(raw);
if (!["http:", "https:"].includes(url.protocol)) throw new Error("protocol blocked");
const { address } = await lookup(url.hostname);
if (BLOCKED.some((re) => re.test(address))) throw new Error("ssrf blocked");
}// src/routes/preview.ts
app.post("/preview", async (req, res) => {
const { targetUrl } = z.object({ targetUrl: z.string().url() }).parse(req.body);
await assertSafeUrl(targetUrl);
const html = await fetch(targetUrl, { signal: AbortSignal.timeout(3_000) });
res.send(await html.text());
});O que isso demonstra:
- Variáveis de ambiente validadas na inicialização - a falta de
JWT_SECRETfalha antes de iniciar o servidor. - Proteção SSRF resolve DNS e bloqueia IPs privados.
- Zod valida a estrutura da entrada antes da requisição externa.
Mergulho Profundo
Como Funciona
- Valide na fronteira de confiança (borda HTTP), não profundamente nos repositórios.
- Segredos nunca são registrados; redija em serializadores de logger estruturados.
- Use helmet ou plugins de framework para cabeçalhos de segurança.
- Limite a taxa de autenticação e endpoints caros na borda ou em middleware.
Tabela de Regras de Segurança
| Regra | Aplicação |
|---|---|
| Valide todas as entradas | Zod/schema na rota |
| Segredos apenas em env/cofre | gitignore, scanners de segredos |
| Proteção SSRF em requisições de saída | DNS + lista de bloqueio de IP |
| Configuração explícita de Helmet/CORS | middleware |
npm audit alto+ bloqueado | CI |
Notas de TypeScript
z.infer<typeof Schema>tipa os dados validados.- Evite
anyemreq.body- o tipo vem apenas do resultado do parse.
Armadilhas
- Confiar em
req.bodyapós validação parcial - Campos extras passados para o ORM. Correção:.strict()em objetos Zod. - Registrar corpos de requisição completos - PII em logs. Correção: apenas lista de permissão de campos no log.
- JWT em strings de consulta - Vazamentos via logs e Referer. Correção: apenas cabeçalho Authorization.
- CORS
*padrão com credenciais - Violação de segurança do navegador e vazamento de dados. Correção: lista de permissão de origem explícita. - Poluição de protótipo via
Object.assign(req.body)- UsestructuredCloneou o objeto de saída do parse do schema.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| joi / valibot | Padrão da equipe | Já padronizado em Zod |
| WAF na borda | DDoS, regras OWASP | Substituir validação de entrada |
| mTLS interno | Malha de serviço zero trust | Apenas REST público |
FAQs
O limite do express.json() é suficiente?
Defina { limit: "100kb" } mais validação de schema; payloads grandes precisam de endpoints de streaming separadamente.
Qual o tamanho do segredo JWT?
Mínimo de 32 bytes aleatórios; rotacione com janela de verificação de chave dupla.
Rebiding DNS SSRF?
Resolva e conecte ao IP no mesmo wrapper de requisição protegido; timeout curto; bloqueie redirecionamentos para IPs privados.
Validação Fastify?
Use @fastify/type-provider-typebox ou compilador Zod - valide antes que o handler seja executado.
NestJS ValidationPipe?
Habilite globalmente com whitelist: true e forbidNonWhitelisted: true.
Escaneamento de dependências é suficiente?
Não. Combine auditoria, Socket e regras de codificação segura; scanners perdem falhas na lógica do aplicativo.
Como lidar com uploads de arquivos?
Escaneie tipo/tamanho; armazene fora da raiz web; nunca execute conteúdo carregado.
Segredos no Docker?
Injete em tempo de execução via segredos do orquestrador; não argumentos de build incorporados nas camadas da imagem.
Onde limitar taxa?
Gateway de API ou @fastify/rate-limit / express-rate-limit em rotas de autenticação no mínimo.
Conjunto mínimo de cabeçalhos de segurança?
Content-Security-Policy (API JSON pode ser mínima), X-Content-Type-Options, Strict-Transport-Security atrás de TLS.
Relacionados
- Lista de Verificação de Regras de Projeto Node - regras 6-10
- Regras de Dependência - cadeia de suprimentos
- Regras de API - limites de exposição de erros
Versões da Stack: Esta página foi escrita para Node.js 24.18.0 (LTS Ativo), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, e NestJS 11.