Subresource Integrity em Microfrontends: Blindagem Essencial para sua Arquitetura
Como implementar Subresource Integrity (SRI) em microfrontends para garantir segurança contra código malicioso, ataques a CDNs e modificações não autorizadas em módulos carregados dinamicamente.
Em arquiteturas modernas com Micro Frontends (MFE), especialmente aquelas que utilizam importmap ou System.import() com frameworks como single-spa, é comum carregar módulos JavaScript dinamicamente a partir de CDNs ou buckets públicos. No entanto, essa flexibilidade traz desafios significativos de segurança.
🚨 O Desafio
Carregamento Dinâmico
- ❌ Módulos carregados em tempo de execução
- ❌ Execução de código malicioso se arquivos forem comprometidos
- ❌ Falta de verificação de integridade
Ambientes Distribuídos
- ❌ Múltiplos times e pipelines de CI/CD
- ❌ Garantir integridade dos módulos se torna complexo
- ❌ Coordenação difícil entre equipes
CDNs e Buckets Públicos
- ❌ Recursos hospedados em terceiros
- ❌ Alvo de ataques ou modificações não autorizadas
- ❌ Falta de controle sobre o conteúdo servido
✅ A Solução: Subresource Integrity (SRI) com Import Maps
A recente introdução do campo "integrity" nos importmaps permite especificar hashes criptográficos para cada módulo, garantindo que apenas o código esperado seja executado pelo navegador. Essa funcionalidade já é suportada nativamente no Chrome e pode ser utilizada em outros navegadores com o auxílio de polyfills como o ES Module Shims.
Exemplo de Import Map com SRI:
<script type="importmap">
{
"imports": {
"app": "https://cdn.example.com/[email protected]/index.js",
"react": "https://cdn.example.com/[email protected]/index.js",
"vue": "https://cdn.example.com/[email protected]/index.js"
},
"integrity": {
"https://cdn.example.com/[email protected]/index.js": "sha384-abc123def456...",
"https://cdn.example.com/[email protected]/index.js": "sha384-xyz789ghi012...",
"https://cdn.example.com/[email protected]/index.js": "sha384-mno345pqr678..."
}
}
</script>
🔐 Como Gerar o Hash de Integridade
Comando para Gerar SHA-384:
cat index.js | openssl dgst -sha384 -binary | openssl base64 -A
Exemplo Prático:
# Gerar hash para um arquivo específico
openssl dgst -sha384 -binary dist/app.js | openssl base64 -A
# Resultado: sha384-abc123def456ghi789jkl012mno345pqr678stu901vwx234yz567...
Script Automatizado:
#!/bin/bash
# generate-sri.sh
generate_sri() {
local file=$1
local hash=$(openssl dgst -sha384 -binary "$file" | openssl base64 -A)
echo "sha384-$hash"
}
# Gerar hashes para todos os arquivos JS
for file in dist/*.js; do
echo "$(basename "$file"): $(generate_sri "$file")"
done
🛠️ Integração com CI/CD
JSPM Generator
Ferramentas como o JSPM Generator facilitam a geração automática de import maps com hashes de integridade, integrando-se perfeitamente aos pipelines de CI/CD.
# Instalar JSPM Generator
npm install -g @jspm/generator
# Gerar import map com SRI
jspm generate --integrity --map dist/
GitHub Actions Example:
# .github/workflows/build-and-deploy.yml
name: Build and Deploy with SRI
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Generate SRI hashes
run: |
# Gerar hashes para todos os arquivos JS
for file in dist/*.js; do
hash=$(openssl dgst -sha384 -binary "$file" | openssl base64 -A)
echo "sha384-$hash" > "${file}.sri"
done
- name: Update import map
run: |
# Atualizar import map com hashes gerados
node scripts/update-importmap.js
- name: Deploy to CDN
run: |
# Deploy para CDN com arquivos e import map
aws s3 sync dist/ s3://your-cdn-bucket/
⚠️ Casos Reais de Comprometimento
Ataques a CDNs
- 🚨 Polyfill.io: O recente ataque demonstrou como a falta de verificação de integridade pode levar à injeção de código malicioso em larga escala
- 🚨 Bootstrap CDN: Histórico de ataques similares em CDNs populares
- 🚨 jQuery CDN: Vulnerabilidades exploradas através de modificações não autorizadas
Modificações Não Autorizadas
- 🚨 Versões antigas de módulos sobrescritas inadvertidamente
- 🚨 Vulnerabilidades introduzidas por mudanças não controladas
- 🚨 Código malicioso injetado em ambientes de produção
🛡️ Boas Práticas
1. Utilize SRI em Todos os Módulos
<!-- ✅ Bom: SRI em todos os módulos -->
<script type="importmap">
{
"imports": {
"app": "https://cdn.example.com/[email protected]/index.js",
"vendor": "https://cdn.example.com/[email protected]/index.js"
},
"integrity": {
"https://cdn.example.com/[email protected]/index.js": "sha384-abc123...",
"https://cdn.example.com/[email protected]/index.js": "sha384-xyz789..."
}
}
</script>
2. Combine com Políticas de Segurança
<!-- Content Security Policy com SRI obrigatório -->
<meta http-equiv="Content-Security-Policy"
content="require-sri-for script; script-src 'self' https://cdn.example.com;">
3. Automatize no Pipeline
// scripts/update-importmap.js
const fs = require('fs');
const crypto = require('crypto');
function generateSRI(filePath) {
const content = fs.readFileSync(filePath);
const hash = crypto.createHash('sha384').update(content).digest('base64');
return `sha384-${hash}`;
}
function updateImportMap() {
const importMap = {
imports: {
"app": "https://cdn.example.com/[email protected]/index.js"
},
integrity: {}
};
// Gerar hash para cada arquivo
const files = ['dist/app.js', 'dist/vendor.js'];
files.forEach(file => {
const url = `https://cdn.example.com/${file}`;
importMap.integrity[url] = generateSRI(file);
});
// Salvar import map atualizado
fs.writeFileSync('dist/importmap.json', JSON.stringify(importMap, null, 2));
}
updateImportMap();
🔧 Implementação Prática
Single-SPA com SRI
// main.js
import { registerApplication, start } from 'single-spa';
// Import map com SRI
const importMap = {
imports: {
"react": "https://cdn.example.com/[email protected]/index.js",
"vue": "https://cdn.example.com/[email protected]/index.js"
},
integrity: {
"https://cdn.example.com/[email protected]/index.js": "sha384-abc123...",
"https://cdn.example.com/[email protected]/index.js": "sha384-xyz789..."
}
};
// Registrar aplicações com SRI
registerApplication({
name: 'react-app',
app: () => System.import('react'),
activeWhen: '/react'
});
registerApplication({
name: 'vue-app',
app: () => System.import('vue'),
activeWhen: '/vue'
});
start();
Fallback para Navegadores Antigos
<!-- ES Module Shims para suporte a SRI em navegadores antigos -->
<script async src="https://ga.jspm.io/npm:[email protected]/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"app": "https://cdn.example.com/[email protected]/index.js"
},
"integrity": {
"https://cdn.example.com/[email protected]/index.js": "sha384-abc123..."
}
}
</script>
📊 Monitoramento e Alertas
Verificação de Integridade
// Verificar integridade em tempo de execução
function verifyIntegrity(url, expectedHash) {
return fetch(url)
.then(response => response.arrayBuffer())
.then(buffer => {
const hash = crypto.subtle.digest('SHA-384', buffer);
return hash.then(hashBuffer => {
const hashArray = new Uint8Array(hashBuffer);
const hashBase64 = btoa(String.fromCharCode(...hashArray));
return `sha384-${hashBase64}` === expectedHash;
});
});
}
// Uso
verifyIntegrity(
'https://cdn.example.com/[email protected]/index.js',
'sha384-abc123...'
).then(isValid => {
if (!isValid) {
console.error('❌ Integridade comprometida!');
// Implementar alertas ou fallbacks
}
});
🚀 Benefícios da Implementação
Segurança
- ✅ Proteção contra código malicioso injetado
- ✅ Verificação de integridade automática
- ✅ Prevenção de ataques a CDNs
Confiabilidade
- ✅ Garantia de código válido em produção
- ✅ Prevenção de modificações não autorizadas
- ✅ Auditoria de integridade completa
Compliance
- ✅ Atendimento a padrões de segurança
- ✅ Documentação de integridade para auditorias
- ✅ Rastreabilidade de mudanças
📋 Checklist de Implementação
- Gerar hashes SRI para todos os módulos
- Atualizar import maps com campos de integridade
- Implementar CSP com require-sri-for
- Automatizar geração no pipeline CI/CD
- Configurar monitoramento de integridade
- Implementar fallbacks para navegadores antigos
- Documentar processo de atualização de hashes
- Treinar equipe sobre boas práticas de SRI
Este artigo apresenta uma medida essencial de segurança para arquiteturas de microfrontends. A implementação de Subresource Integrity protege contra ataques e garante que apenas código validado seja executado. Para discussões técnicas, implementações ou dúvidas sobre segurança em microfrontends, me encontre no LinkedIn ou GitHub.