Helmet é um middleware para aplicações Node.js que configura cabeçalhos HTTP relacionados à segurança. Ele reduz a exposição a ataques comuns no navegador, como carregamento de recursos não autorizados, interpretação incorreta de tipos de conteúdo, clickjacking e vazamento de informações por cabeçalhos.
O Helmet não torna uma aplicação automaticamente segura. Ele complementa validação de entrada, autenticação, autorização, proteção CSRF, cookies seguros, TLS, rate limiting e atualização de dependências.
Instalação
npm install helmetEm Express:
import express from 'express';
import helmet from 'helmet';
const app = express();
app.use(helmet());
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
app.listen(3000);A configuração padrão habilita vários cabeçalhos com valores seguros. Antes de levar para produção, teste frontend, documentação, uploads, iframes e integrações externas.
Content-Security-Policy
A Content Security Policy, ou CSP, controla de onde scripts, estilos, imagens, fontes e conexões podem ser carregados. É uma das proteções mais importantes contra XSS, mas também a que exige mais planejamento.
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"],
styleSrc: ["'self'"],
imgSrc: ["'self'", 'data:', 'https:'],
connectSrc: ["'self'", 'https://api.example.com'],
objectSrc: ["'none'"],
frameAncestors: ["'none'"],
upgradeInsecureRequests: [],
},
},
}));Evite liberar 'unsafe-inline' ou 'unsafe-eval' sem uma justificativa técnica. Para scripts inline, prefira nonce ou hash.
Nonce por resposta
import crypto from 'node:crypto';
app.use((req, res, next) => {
res.locals.cspNonce = crypto.randomBytes(16).toString('base64');
next();
});
app.use(helmet({
contentSecurityPolicy: {
directives: {
scriptSrc: [
"'self'",
(req, res) => `'nonce-${res.locals.cspNonce}'`,
],
},
},
}));O template precisa inserir o mesmo nonce no elemento permitido:
<script nonce="{{cspNonce}}" src="/app.js"></script>Gere um nonce novo para cada resposta e não o reutilize como segredo de sessão.
Strict-Transport-Security
HSTS instrui o navegador a usar HTTPS durante um período:
app.use(helmet.hsts({
maxAge: 15552000,
includeSubDomains: true,
preload: false,
}));Habilite somente quando o domínio e os subdomínios funcionarem corretamente em HTTPS. Uma política longa configurada cedo demais pode causar indisponibilidade difícil de reverter.
X-Content-Type-Options
O valor nosniff reduz interpretação de conteúdo com tipo diferente do declarado. Mesmo com o cabeçalho, configure Content-Type corretamente e valide uploads.
Frameguard
Frameguard reduz clickjacking:
app.use(helmet.frameguard({ action: 'deny' }));Quando a aplicação precisa ser incorporada por domínios específicos, use principalmente a diretiva CSP frame-ancestors, que oferece controle mais flexível.
Referrer-Policy
app.use(helmet.referrerPolicy({
policy: 'strict-origin-when-cross-origin',
}));A política controla quanto da URL anterior é enviado no cabeçalho Referer. Evite colocar tokens, emails ou dados sensíveis em URLs, independentemente da política.
Cross-Origin-Resource-Policy
CORP controla quais origens podem carregar determinados recursos:
app.use(helmet.crossOriginResourcePolicy({
policy: 'same-site',
}));APIs, CDNs e frontends hospedados em domínios diferentes precisam de teste. Uma configuração restrita pode bloquear imagens e arquivos legítimos.
Cross-Origin-Opener-Policy
COOP isola o contexto de navegação de documentos de outras origens. Isso reduz certos ataques de canal lateral, mas pode interferir em login por popup e integrações externas.
Cross-Origin-Embedder-Policy
COEP é necessário para alguns recursos de isolamento avançado, mas exige que recursos incorporados forneçam cabeçalhos compatíveis. Não habilite sem inventariar scripts, fontes, imagens e workers.
Desabilitando uma proteção específica
app.use(helmet({
crossOriginEmbedderPolicy: false,
}));Desabilitar pode ser necessário durante migração, mas registre a razão, o responsável e a data para revisão. Não copie uma configuração permissiva sem entender o impacto.
APIs JSON
Uma API sem páginas HTML ainda se beneficia de HSTS, nosniff, políticas de referrer e remoção de cabeçalhos. CSP tem efeito principalmente em documentos carregados pelo navegador, mas pode continuar presente de forma consistente.
Removendo X-Powered-By
O Express pode divulgar a tecnologia usada. Helmet normalmente remove esse cabeçalho. A ocultação não substitui correções, mas reduz informação desnecessária.
Proxy reverso
Quando TLS termina no proxy, configure trust proxy corretamente para que redirects e cookies seguros reconheçam HTTPS:
app.set('trust proxy', 1);O valor depende da topologia. Confiar em qualquer proxy pode permitir falsificação de IP e protocolo.
Ambiente de desenvolvimento
upgrade-insecure-requests pode transformar URLs HTTP em HTTPS e dificultar desenvolvimento local. Use configurações explícitas por ambiente, sem desativar a segurança inteira:
const isDevelopment = process.env.NODE_ENV === 'development';
app.use(helmet({
contentSecurityPolicy: {
directives: {
upgradeInsecureRequests: isDevelopment ? null : [],
},
},
}));Modo report-only
Uma CSP pode ser implantada inicialmente em modo de relatório para descobrir violações sem bloquear. Colete relatórios em endpoint protegido, limite tamanho e não confie cegamente nos dados enviados pelo cliente.
Testes automatizados
import request from 'supertest';
const response = await request(app).get('/');
expect(response.headers['x-content-type-options']).toBe('nosniff');
expect(response.headers['content-security-policy']).toContain("default-src 'self'");Teste também que recursos permitidos continuam funcionando e que origens não autorizadas são bloqueadas.
Observabilidade
Monitore violações CSP, erros de frontend após deploy, falhas de login em popup, recursos bloqueados e mudanças de configuração. Não registre URLs completas quando contêm dados sensíveis.
Erros comuns
- instalar Helmet e considerar a segurança concluída;
- usar CSP com
unsafe-inlineem todo o site; - habilitar HSTS longo sem testar subdomínios;
- desativar proteções para corrigir um único recurso;
- não validar uploads e Content-Type;
- ignorar proxies e HTTPS;
- não testar login, iframes e CDNs;
- copiar políticas sem inventário de recursos.
Fluxo recomendado
- ative a configuração padrão;
- inventarie recursos externos;
- defina CSP restritiva;
- use nonce ou hash;
- teste em report-only;
- corrija violações legítimas;
- habilite bloqueio;
- monitore regressões.
Combine Helmet com TLS e HTTPS no Node.js, Rate Limiting, logs com Pino e gerenciamento de segredos.
Consulte a documentação oficial do Helmet e a referência de Content Security Policy da MDN.




