Cheatsheet e decision tree de segurança
TL;DR
Referência consolidada de decisões de segurança para Node.js senior. O galho 8 cobre 9 áreas críticas: supply chain (npm audit + socket.dev), segredos (vault, env validation com Zod), validação de entrada (Zod vs Joi), JWT (jsonwebtoken, refresh token rotation, Redis blacklist), OAuth 2.0/OIDC (openid-client, PKCE), autorização (casl ABAC vs casbin policies), rate limiting (express-rate-limit + Redis), HTTP headers (Helmet.js) e OWASP Top 10 (A01–A10 com exemplos Node). Use este cheatsheet como ponto de entrada rápido e decision tree para escolher a ferramenta certa para cada categoria de segurança.
O que é
Este cheatsheet consolida os padrões, ferramentas e decisões de segurança das 9 notas do galho 8 da trilha Node Senior. Não é um resumo superficial — é um mapa de decisão para situações reais: qual biblioteca escolher, qual padrão aplicar, o que checar em um PR de segurança.
Quando usar este cheatsheet:
- Início de projeto: escolher o stack de segurança correto
- Code review: validar que as decisões de segurança estão corretas
- Entrevista: responder perguntas transversais sobre segurança Node.js senior
- Incidente: identificar rapidamente qual área pode ter falhado
Como funciona
Decision tree — escolha a ferramenta certa
flowchart TD A[Precisa de segurança em Node.js] --> B{Qual área?} B --> C[Validação de entrada] B --> D[Autenticação] B --> E[Autorização] B --> F[Proteção de API] B --> G[Supply chain] B --> H[Segredos] B --> I[HTTP Headers] C --> C1{TypeScript?} C1 -->|Sim| C2[Zod v3\nsafeParse + infer] C1 -->|Legado JS| C3[Joi v17\nschema object-based] D --> D1{OAuth/OIDC externo?} D1 -->|Sim| D2[openid-client v5\nIssuer.discover + PKCE] D1 -->|JWT próprio| D3[jsonwebtoken v9\nHS256 ou RS256] D3 --> D4[Access + Refresh tokens\nBlacklist no Redis] E --> E1{Regras baseadas em atributos?} E1 -->|Sim, TypeScript| E2[casl v6\ndefineAbility + can/cannot] E1 -->|Políticas externas| E3[casbin\npolicy files + enforce] E1 -->|RBAC simples| E4[Claims no JWT\ncheckRole middleware] F --> F1[express-rate-limit v7\n+ rate-limit-redis\nstore Redis para múltiplas instâncias] G --> G1[npm audit\n+ npm ci no CI\n+ socket.dev ou snyk] H --> H1{Produção?} H1 -->|Sim| H2[AWS Secrets Manager\nHashiCorp Vault\nDoppler] H1 -->|Dev| H3[.env local\nnode --env-file=.env\nValidar com Zod na inicialização] I --> I1["Helmet v7\napp.use(helmet())\nCSP com nonce para scripts inline"]
Tabela comparativa por categoria
| Categoria | Biblioteca principal | Quando usar | Alternativa |
|---|---|---|---|
| Validação de entrada | Zod v3 | TypeScript, schema-first, infer de tipos | Joi v17 (legado JS) |
| Autenticação JWT | jsonwebtoken v9 | JWT próprio, stateless, microservices | @fastify/jwt para Fastify |
| OAuth 2.0 / OIDC | openid-client v5 | Login social, SSO enterprise, Authorization Code + PKCE | passport-oauth2 (flows simples) |
| Autorização | casl v6 | ABAC TypeScript, permissões condicionais, NestJS | casbin (policies em arquivo) |
| HTTP Headers | Helmet v7 | Qualquer app Express — padrão obrigatório | @fastify/helmet para Fastify |
| Rate Limiting | express-rate-limit v7 | Auth endpoints, APIs públicas | @fastify/rate-limit para Fastify |
| Supply chain | npm audit + socket.dev | CI/CD pipeline, pre-merge check | Snyk, Dependabot (GitHub) |
| Segredos em prod | AWS Secrets Manager / Vault | Rotação automática, auditoria de acesso | GCP Secret Manager, Doppler |
Checklist de segurança para PR review
Use este checklist em code reviews que tocam lógica de negócio ou infra:
## Security Review
### Validação e sanitização
- [ ] Input externo validado com Zod/Joi na borda do sistema (controller/route handler)
- [ ] Nenhum `req.body` ou `req.query` passado diretamente para query de banco ou sistema de arquivos
- [ ] Tamanho máximo de strings e arrays definido no schema (previne ReDoS e DoS)
### Segredos
- [ ] Nenhum segredo hardcoded no código (API keys, passwords, tokens)
- [ ] Nenhum `.env` de produção no repositório
- [ ] Env vars validadas com Zod na inicialização — app falha rápido se variável estiver ausente
### Autenticação e sessão
- [ ] `jwt.verify()` chamado com `{ algorithms: ['HS256'] }` explícito (previne algorithm confusion)
- [ ] Refresh tokens com rotação (revoga o anterior ao emitir o novo)
- [ ] Mensagens de erro de auth genéricas (não vazar se email existe ou não)
### Autorização
- [ ] Verificação de ownership feita server-side, não apenas no frontend
- [ ] Usuário pode acessar apenas seus próprios recursos (BOLA/IDOR check)
- [ ] Logs de decisões de autorização negadas registrados (auditoria)
### HTTP e headers
- [ ] `helmet()` aplicado globalmente antes das rotas
- [ ] CSP configurada — sem `'unsafe-inline'` nos scripts (exceto se usando nonces)
- [ ] CORS allowlist explícita, não `*` com `credentials: true`
### Rate limiting
- [ ] Rate limiting aplicado em endpoints de autenticação (login, reset de senha)
- [ ] Store Redis configurado (não memória) em ambientes com múltiplas instâncias
### Supply chain
- [ ] `npm audit` sem vulnerabilidades high/critical
- [ ] `package-lock.json` ou `pnpm-lock.yaml` commitado e usado com `npm ci` no CI
### Logging
- [ ] Dados sensíveis redactados nos logs (senha, token, CPF, cartão)
- [ ] Stack traces não expostos em respostas de API em produção
- [ ] Eventos de autenticação (login, logout, falhas) logados com user_id e IP
Padrões de resposta de erro segura
Erros mal formatados são um vetor de information disclosure. O padrão correto é genérico para o cliente e detalhado internamente.
import express, { Request, Response, NextFunction } from 'express'
interface AppError extends Error {
statusCode?: number
code?: string
isOperational?: boolean
}
// Formato de erro público — sem detalhes internos
interface ErrorResponse {
error: {
code: string
message: string
}
}
function errorHandler(
err: AppError,
req: Request,
res: Response,
_next: NextFunction,
): void {
// Log completo interno (stack trace, contexto)
console.error({
message: err.message,
stack: err.stack,
path: req.path,
method: req.method,
ip: req.ip,
})
// Resposta pública: sem stack trace, mensagem genérica para erros não operacionais
const statusCode = err.statusCode ?? 500
const isOperational = err.isOperational ?? false
const response: ErrorResponse = {
error: {
code: err.code ?? 'INTERNAL_ERROR',
// Erros não operacionais (bugs) → mensagem genérica
// Erros operacionais (validação, negócio) → mensagem da aplicação
message: isOperational ? err.message : 'An unexpected error occurred',
},
}
res.status(statusCode).json(response)
}
// Erros de autenticação: sempre genérico — não vazar se email existe
function authErrorResponse(res: Response): void {
// 401 correto para auth failure (não 400 — isso vaza informação de que o email existe)
res.status(401).json({
error: {
code: 'AUTH_FAILED',
message: 'Invalid credentials',
},
})
}
// 401 vs 403: regra clara
// 401 Unauthorized → não autenticado (sem token ou token inválido)
// 403 Forbidden → autenticado mas sem permissão para o recurso
function authorizationErrorResponse(res: Response, isAuthenticated: boolean): void {
if (!isAuthenticated) {
res.status(401).json({ error: { code: 'UNAUTHENTICATED', message: 'Authentication required' } })
} else {
res.status(403).json({ error: { code: 'FORBIDDEN', message: 'You do not have permission to access this resource' } })
}
}
export { errorHandler, authErrorResponse, authorizationErrorResponse }Bootstrap seguro da aplicação
Configuração mínima de segurança para uma aplicação Express em produção:
import express from 'express'
import helmet from 'helmet'
import rateLimit from 'express-rate-limit'
import { z } from 'zod'
import crypto from 'node:crypto'
// 1. Validar env vars na inicialização — falha rápido se algo estiver ausente
const EnvSchema = z.object({
NODE_ENV: z.enum(['development', 'test', 'production']),
JWT_SECRET: z.string().min(32, 'JWT_SECRET must be at least 32 characters'),
DATABASE_URL: z.string().url(),
REDIS_URL: z.string().url(),
PORT: z.coerce.number().default(3000),
ALLOWED_ORIGINS: z.string().transform((val) => val.split(',')),
})
const env = EnvSchema.parse(process.env)
const app = express()
// 2. Helmet — headers de segurança HTTP (antes de qualquer rota)
app.use(
helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", (_req, res) => `'nonce-${(res as any).locals.nonce}'`],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", 'data:', 'https:'],
},
},
}),
)
// Gerar nonce por request (para CSP com scripts inline)
app.use((_req, res, next) => {
res.locals.nonce = crypto.randomBytes(16).toString('base64')
next()
})
// 3. CORS com allowlist explícita
app.use((_req, res, next) => {
const origin = _req.headers.origin
if (origin && env.ALLOWED_ORIGINS.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin)
res.setHeader('Access-Control-Allow-Credentials', 'true')
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization')
}
if (_req.method === 'OPTIONS') {
res.sendStatus(204)
return
}
next()
})
// 4. Rate limiting global
const globalLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
limit: 100,
standardHeaders: 'draft-7',
legacyHeaders: false,
})
app.use(globalLimiter)
// 5. Rate limiting restrito para auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000,
limit: 10,
message: { error: { code: 'RATE_LIMIT_EXCEEDED', message: 'Too many authentication attempts' } },
standardHeaders: 'draft-7',
legacyHeaders: false,
})
app.use('/auth', authLimiter)
// 6. Body parsing com limite de tamanho
app.use(express.json({ limit: '10kb' }))
export { app, env }JWT verify com proteção contra algorithm confusion
import jwt from 'jsonwebtoken'
import { z } from 'zod'
const JwtPayloadSchema = z.object({
sub: z.string(),
email: z.string().email(),
role: z.enum(['admin', 'user', 'moderator']),
iat: z.number(),
exp: z.number(),
})
type JwtPayload = z.infer<typeof JwtPayloadSchema>
function verifyAccessToken(token: string, secret: string): JwtPayload {
// Sempre passar algorithms explicitamente — previne algorithm confusion attack
// Se omitir, um atacante pode forjar token com alg: "none" ou trocar HS256 por RS256
const raw = jwt.verify(token, secret, { algorithms: ['HS256'] })
// Validar estrutura do payload com Zod — jwt.verify não valida claims customizados
const result = JwtPayloadSchema.safeParse(raw)
if (!result.success) {
throw new Error('Invalid token payload structure')
}
return result.data
}
export { verifyAccessToken, JwtPayload }Armadilhas comuns
CORS com
*ecredentials: trueé inválido e perigosoConfigurar
Access-Control-Allow-Origin: *junto comAccess-Control-Allow-Credentials: trueviola a spec CORS e browsers modernos bloqueiam a requisição. Mais grave: alguns proxies e configurações incorretas de gateway aceitam e repassam ambos os headers, expondo APIs autenticadas a qualquer origem. A configuração correta é sempre uma allowlist explícita de origens:res.setHeader('Access-Control-Allow-Origin', allowedOrigin)ondeallowedOriginé validado contra uma lista de origens aprovadas.
Erros de auth com mensagem específica vazam informação
Retornar
"User not found"vs"Wrong password"permite a um atacante confirmar quais emails estão cadastrados (user enumeration attack). A mitigação é sempre retornar a mesma mensagem genérica:"Invalid credentials"— e tomar o mesmo tempo para processar ambos os casos (comparação de hash mesmo quando o usuário não existe, usandobcrypt.comparecom um hash fake para evitar timing attack).
jwt.verify sem algorithms abre brecha de algorithm confusion
jwt.verify(token, secret)sem{ algorithms: ['HS256'] }aceita qualquer algoritmo declarado no header do token, incluindo"none". Um atacante pode criar um token sem assinatura comalg: "none"e bypassar a verificação. Sempre passe o array de algoritmos aceitos explicitamente.
Rate limiting em memória não funciona em múltiplas instâncias
O store padrão do
express-rate-limité em memória (por processo). Em um cluster com 4 workers ou 3 pods Kubernetes, cada instância tem seu próprio contador — o limite efetivo é multiplicado pelo número de instâncias. Userate-limit-rediscom um store Redis compartilhado para garantir que o limite seja global.
Em entrevista
Q: How would you secure a Node.js REST API end-to-end?
A: I’d think of security in layers. At the network layer, HTTPS everywhere and a reverse proxy handling TLS termination. At the HTTP layer, Helmet.js for security headers — CSP, HSTS, X-Frame-Options — and rate limiting on all endpoints, stricter on authentication. At the application boundary, all external input validated with Zod before touching any business logic. For authentication, JWTs with short expiry signed with HS256 or RS256 (never alg: none), plus a refresh token rotation pattern with a Redis blacklist. Authorization is checked server-side on every request — ownership verification for resource access to prevent BOLA/IDOR. Secrets never in code, only from environment variables validated at startup, pulled from AWS Secrets Manager or Vault in production. And supply chain: npm ci in CI, npm audit as a pipeline gate, socket.dev for real-time package threat analysis.
Q: What’s the difference between authentication and authorization, and how do you implement both in Node.js?
A: Authentication answers “who are you?” — verifying identity. Authorization answers “what are you allowed to do?” — verifying permissions. They must always happen in that order, and on the server side. In Node.js, authentication typically means validating a JWT with jsonwebtoken’s verify() using an explicit algorithms array, or running an OIDC flow with openid-client. Authorization for simple role-based rules can live in JWT claims with a checkRole middleware, but for anything conditional — like “users can only edit their own posts” — I use casl, which lets me express can('update', 'Post', { authorId: user.id }) and check it against the actual resource. The key mistake is checking authorization only in the frontend, or forgetting to verify ownership when the user provides a resource ID in the URL.
Q: How do you prevent OWASP A01 Broken Access Control in a Node.js API?
A: A01 is consistently the top OWASP risk because it’s easy to miss. The main patterns I protect against are BOLA (Broken Object Level Authorization) — where a user accesses another user’s resource by changing an ID in the URL — and privilege escalation. For BOLA, the rule is: never trust IDs from the request alone. Always verify ownership server-side: WHERE id = ? AND owner_id = ?. For privilege escalation, I never let users set their own role via API, and I check the role from the JWT, not from the database row the user controls. In code reviews I specifically look for routes that accept a resource ID without verifying it belongs to the authenticated user — that pattern appears constantly in CRUD APIs.
Q: How do you handle secrets in a Node.js production environment?
A: The principles are: secrets never in source code, never in environment variables baked into Docker images, and rotatable without downtime. In production I pull secrets from AWS Secrets Manager or HashiCorp Vault at startup, using the SDK — the app crashes fast if a required secret is missing, which is better than running with a wrong configuration. I validate all environment variables with a Zod schema at boot: EnvSchema.parse(process.env). For rotation, the pattern is to support two valid versions of a secret simultaneously during the rotation window — issue new JWTs signed with the new key, keep accepting old ones until they expire. No manual secret rotation that requires a deployment.
Vocabulário
- Supply chain attack: ataque que compromete uma dependência (pacote npm, build tool, CI pipeline) em vez de atacar diretamente a aplicação
- BOLA (Broken Object Level Authorization): vulnerabilidade onde um usuário acessa recursos de outro usuário alterando um ID na requisição; sinônimo de IDOR (Insecure Direct Object Reference)
- Algorithm confusion: ataque JWT onde o atacante altera o campo
algdo header paranoneou troca RS256 por HS256, bypassando verificação de assinatura quandoalgorithmsnão é passado explicitamente aoverify() - SSRF (Server-Side Request Forgery): vulnerabilidade onde o servidor realiza requisições HTTP a destinos controlados pelo atacante — pode expor metadados de cloud (169.254.169.254) ou serviços internos
- CSP (Content Security Policy): header HTTP que instrui o browser sobre quais origens de scripts, estilos e recursos são permitidas — principal defesa contra XSS
- HSTS (HTTP Strict Transport Security): header que instrui o browser a sempre usar HTTPS para o domínio pelo período definido em
maxAge, impedindo downgrade para HTTP - Rate limiting: mecanismo que limita o número de requisições de uma origem em uma janela de tempo — protege contra brute force, DoS e abuso de API
- Input validation: verificação que dados externos (req.body, req.query, req.params) obedecem o schema esperado antes de qualquer processamento — primeira linha de defesa contra injection
- Least privilege: princípio de segurança onde um usuário, serviço ou processo recebe apenas as permissões mínimas necessárias para sua função
- Secret rotation: processo de substituição periódica de segredos (API keys, JWT secrets, DB passwords) sem downtime — requer suporte a múltiplas versões válidas durante a transição
- CVE (Common Vulnerabilities and Exposures): identificador único para vulnerabilidades de segurança conhecidas; reportado por
npm audit - Timing attack: ataque que mede diferenças de tempo de resposta para inferir informação — e.g., comparar strings com
===em vez decrypto.timingSafeEqualvaza se o hash começou a divergir
Casos práticos
Auditoria de segurança antes de go-live
A equipe tem 48 horas antes do lançamento de uma API em produção e precisa de uma auditoria rápida de segurança. O cheatsheet serve como roteiro: a engenheira de segurança percorre o checklist de PR review item a item, abrindo issues para cada ponto falho encontrado.
Resultado da auditoria em um caso típico: 3 endpoints de autenticação sem rate limiting (critica — OWASP A04), jwt.verify sem { algorithms } em dois middlewares (crítica — A07), CSP com unsafe-inline para scripts (alta — A05), dois segredos hardcoded em arquivo de configuração de staging (alta — A02), e npm install em vez de npm ci no Dockerfile (média — A08).
A priorização é direta pelo critério de impacto: os dois itens críticos bloqueiam o go-live. Os três itens de alta prioridade entram no sprint seguinte. O time não precisa conhecer de cabeça todo o OWASP Top 10 — o cheatsheet opera como externalização de memória especializada, reduzindo o risco de omissão em revisões de tempo curto.
# Sequência de auditoria rápida com CLI
npm audit --audit-level=high # dependências com CVE high/critical
grep -r "Math.random()" src/ # tokens inseguros
grep -rn "jwt.verify" src/ | grep -v "algorithms" # jwt sem algorithm fixo
grep -rn "process.env\." src/ | grep -v "env\." # env vars sem validação centralizada
grep -rn "console.log.*password\|console.log.*token" src/ # logs com dados sensíveisOnboarding de desenvolvedor junior em segurança Node.js
Um engenheiro júnior entra no time e precisa aprender as práticas de segurança do projeto em uma semana. Em vez de ler as 9 notas do galho sequencialmente (sobrecarga), o tech lead usa esta nota como ponto de entrada:
- Dia 1: decision tree — qual ferramenta para cada área de segurança e por quê
- Dia 2: checklist de PR — ler o checklist, depois revisar um PR real de auth e identificar o que está correto e o que está faltando
- Dia 3: padrões de resposta de erro e bootstrap seguro — entender por que mensagens genéricas e por que
zod.parsena inicialização - Dia 4: aprofundar nas notas das áreas mais fracas (ex: se nunca trabalhou com JWT, ir para nota 04)
- Dia 5: simular um code review completo usando o checklist como guia
Ao final, o júnior tem o mapa mental correto: “quando vejo um endpoint que aceita ID de recurso, lembro do checklist de BOLA. Quando vejo jwt.verify, verifico se tem algorithms.” O cheatsheet não substitui o entendimento — ele ancora os padrões para o contexto de decisão real.
Escolha entre casl e casbin em um sistema multi-tenant
Um SaaS com múltiplos tenants precisa decidir entre casl e casbin para autorização. A decision tree da nota aponta para a bifurcação correta: casl se as regras são expressas em TypeScript com condicionais de atributos; casbin se as políticas precisam ser gerenciadas externamente (por operadores, sem re-deploy).
O SaaS tem dois perfis de usuário: admins de tenant (gerenciam usuários e dados do próprio tenant) e usuários finais (acessam apenas seus próprios recursos). Há também um super admin da plataforma (acessa qualquer tenant para suporte). Este cenário mistura RBAC (roles fixas: admin, user, super_admin) com ABAC (condições: tenantId, ownerId).
A escolha final é casl: as regras são estáticas o suficiente para viver no código, TypeScript fornece type safety nas habilidades, e a integração com NestJS via @casl/ability é madura. casbin seria preferível se admins de tenant precisassem configurar regras personalizadas via UI — mas nesse caso o design é fixo.
import { AbilityBuilder, createMongoAbility } from '@casl/ability'
type Actions = 'read' | 'create' | 'update' | 'delete' | 'manage'
type Subjects = 'User' | 'Document' | 'Invoice' | 'Tenant' | 'all'
function defineAbilityFor(user: { role: string; tenantId: string; id: string }) {
const { can, cannot, build } = new AbilityBuilder(createMongoAbility)
if (user.role === 'super_admin') {
// Super admin pode tudo em qualquer tenant
can('manage', 'all')
} else if (user.role === 'tenant_admin') {
// Tenant admin gerencia apenas recursos do próprio tenant
can('manage', ['User', 'Document', 'Invoice'], { tenantId: user.tenantId })
// Mas não pode deletar o próprio tenant (proteção extra)
cannot('delete', 'Tenant')
} else {
// Usuário comum vê e edita apenas seus próprios documentos dentro do tenant
can('read', 'Document', { tenantId: user.tenantId })
can(['create', 'update'], 'Document', { tenantId: user.tenantId, ownerId: user.id })
can('read', 'Invoice', { tenantId: user.tenantId, userId: user.id })
}
return build()
}
// Verificação server-side: sempre com o documento já carregado do banco
async function getDocument(req: express.Request, res: express.Response) {
const doc = await db.document.findUnique({ where: { id: req.params.id } })
if (!doc) return res.status(404).json({ error: 'Not found' })
const ability = defineAbilityFor(req.user)
if (ability.cannot('read', subject('Document', doc))) {
return res.status(403).json({ error: 'Forbidden' })
}
return res.json(doc)
}A decisão casl vs casbin não é técnica apenas — é organizacional. Se o time de produto vai querer no futuro uma interface de configuração de permissões para clientes configurarem suas próprias regras, casbin com adapter de banco é a escolha correta desde o início.
O que vem a seguir
Esta nota encerra o galho 8 de segurança da trilha Node Senior. Para aprofundar cada área:
- OWASP Top 10 para Node — referência completa com exemplos de código para cada categoria A01–A10
- Supply chain attacks e npm audit — npm audit, socket.dev, e políticas de lockfile para A06 e A08
- JWT e jsonwebtoken — implementação completa de access + refresh token com blacklist Redis
- Helmet.js e hardening HTTP — configuração detalhada de CSP com nonces, HSTS e CORS em produção
Fora do galho, as próximas fronteiras naturais são Microservices (segurança inter-serviço: mTLS, service mesh, propagação de contexto) e Observabilidade (correlação de logs de segurança com traces e métricas de anomalia).
O cheatsheet deve ser revisitado a cada nova versão de dependência crítica (helmet, express-rate-limit, jsonwebtoken), pois APIs mudam e novos vetores surgem com o tempo.
Para entrevistas sênior de segurança, o exercício mais valioso é percorrer mentalmente a decision tree e o checklist de PR para um cenário hipotético dado pelo entrevistador — demonstrando não apenas o que fazer, mas o raciocínio sobre por quê cada camada existe e como as categorias OWASP se encadeiam. A profundidade de resposta que separa sênior de pleno nesse tópico é a capacidade de articular os trade-offs (ex: casl vs casbin, npm ci --ignore-scripts e o custo de não ter alguns build scripts) sem depender de memorização de APIs específicas.
Fontes
- OWASP Top 10:2021 — lista oficial com definições, exemplos e guias de prevenção para cada categoria
- OWASP Cheat Sheet Series — índice de guias técnicos para todas as categorias, incluindo Authentication, JWT, SSRF e Injection
- Node.js Security Best Practices — guia oficial Node.js cobrindo DoS, injection, HTTP headers e supply chain
- Helmet.js Documentation — referência oficial de todos os middlewares Helmet v7 e opções de CSP
- express-rate-limit — README — documentação completa incluindo Redis store, keyGenerator e options v7
- casl — Getting Started — guia oficial casl v6 com AbilityBuilder, subject helper e integração com NestJS e React
- OWASP Testing Guide v4.2 — metodologia completa de teste de segurança, incluindo testes de BOLA, authentication bypass e SSRF
- Snyk Learn — Node.js Security — trilha de aprendizado com exemplos práticos de cada categoria OWASP em Node.js, com exercícios interativos
- Socket.dev — análise de ameaças em tempo real para pacotes npm, detectando comportamento suspeito em scripts de instalação antes do
npm install
Veja também
- Segurança — MOC do galho 8
- 01 - Supply chain attacks e npm audit — npm audit, socket.dev, lockfile integrity
- 02 - Segredos e variáveis de ambiente — vault, env validation, rotação de segredos
- 03 - Validação de entrada com Zod e Joi — Zod v3, Joi v17, middleware de validação
- 04 - JWT e autenticação com jsonwebtoken — sign/verify, access+refresh, blacklist Redis
- 05 - OAuth 2.0 e OIDC com openid-client — Authorization Code + PKCE, ID Token, openid-client v5
- 06 - RBAC e ABAC com casl e casbin — defineAbility, can/cannot, casbin policies
- 07 - Rate limiting com express-rate-limit — express-rate-limit v7, Redis store, algoritmos
- 08 - Helmet.js e hardening HTTP — CSP com nonce, HSTS, CORS allowlist
- 09 - OWASP Top 10 para Node — A01–A10 com exemplos Node e mitigações
- Node.js (MOC central) — visão geral de todos os galhos da trilha
- Node.js — tronco da trilha Node Senior
- Segurança em frameworks — como os middlewares do galho Frameworks e arquitetura se integram ao stack de segurança
- Segurança Conceitual (Fundamentos) — base teórica: threat modeling, criptografia assimétrica, protocolos TLS
- Cheatsheet ORMs — cheatsheet do galho de banco de dados, complementar a este para queries parametrizadas e prevenção de injection