Pruebas de penetración de seguridad
Este directorio contiene pruebas centradas en la seguridad para la API de trabajador. Ejecútelos antes de implementarlos en producción.
Inicio rápido
# Audit local secret exposure first
npm run test:secrets
# 1. Start the local Worker (in worker/ directory)
cd worker && npx wrangler dev --port 8787
# 2. Run security tests (in project root)
npm run test:security
# Run against staging
WORKER_URL=https://pledge-staging.example.com npm run test:security
# Run against production (read-only tests only)
WORKER_URL=https://worker.example.com PROD_MODE=true npm run test:security
Configuración de desarrollo local
Para las comprobaciones del webhook del trabajador en vivo, el secreto del webhook de Stripe debe configurarse localmente.
STRIPE_WEBHOOK_SECRET
La forma más sencilla de obtener una configuración local coincidente es:
./scripts/dev.sh
o la puerta de fusión:
npm run test:premerge
npm run test:premerge ahora incluye la auditoría secreta automáticamente ante las suites Worker, Smoke y Browser.
Para que las pruebas de limitación de velocidad funcionen localmente, asegúrese de que el espacio de nombres RATELIMIT KV esté configurado en wrangler.toml. El Trabajador ahora trata esa vinculación como se requiere:
# In [[kv_namespaces]] section (production)
[[kv_namespaces]]
binding = "RATELIMIT"
id = "YOUR_RATELIMIT_KV_ID"
preview_id = "YOUR_RATELIMIT_PREVIEW_ID"
# Also in [[env.dev.kv_namespaces]] section (development)
[[env.dev.kv_namespaces]]
binding = "RATELIMIT"
id = "YOUR_RATELIMIT_KV_ID"
preview_id = "YOUR_RATELIMIT_PREVIEW_ID"
Nota: Reinicie el Worker después de realizar cambios para restablecer los contadores de límite de velocidad (KV se simula localmente y se reinicia al reiniciar).
Categorías de prueba
1. Omisión de autenticación (auth-bypass.test.ts)
- Omisión del token de desarrollo en puntos finales
/votes - Tokens de enlace mágico faltantes o no válidos
- Fichas caducadas
- Firmas de tokens manipuladas
2. Seguridad del webhook (webhook-security.test.ts)
- Firmas de rayas no válidas
- Repetir ataques (mismo ID de evento)
- Cargas útiles de webhooks con formato incorrecto
- Faltan encabezados de firma
- La superficie del webhook de Stripe requiere firmas válidas
3. Autorización (authorization.test.ts)
- Intentos de acceso a promesas de usuarios cruzados
- Acceso al punto final del administrador sin secreto
- Pruebe el acceso al punto final en modo de producción
4. Validación de entrada (input-validation.test.ts)
- Cargas útiles sobredimensionadas
- Babosas de campaña maliciosas
- Patrones de inyección SQL/NoSQL
- Cargas útiles XSS en campos de usuario
5. Limitación de tasa (rate-limiting.test.ts)
- Las ráfagas públicas de
/stats/:slugdeben permanecer sin límites para que la viralidad de la campaña no se trate como abuso - Las solicitudes de ráfaga a
/checkout-intent/startdeberían llegar al depósito de escritura obligatorio - Las lecturas y escrituras de Manage Pledge deberían alcanzar sus propios niveles más altos pero obligatorios.
- Votar intentos de spam (límite de 45 solicitudes/min)
- Simulación de fuerza bruta del administrador (límite de 5 solicitudes/min)
- La prevención del agotamiento de recursos debería rechazar los cuerpos de caja de gran tamaño con
413 - Resiliencia DoS y seguridad de operaciones concurrentes
- Seguridad de operación concurrente
Configuración
Establezca estas variables de entorno:
| variable | Predeterminado | Descripción |
|---|---|---|
WORKER_URL |
http://localhost:8787 |
Punto final del trabajador para probar |
PROD_MODE |
false |
Saltar pruebas destructivas |
ADMIN_SECRET |
(ninguno) | Secreto de administrador para pruebas de autenticación |
TEST_TOKEN |
(ninguno) | Token de enlace mágico válido para pruebas de autenticación |
Integración de CI
Agregar a acciones de GitHub:
security-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm run test:security
env:
WORKER_URL: ${{ secrets.STAGING_WORKER_URL }}
Escribir nuevas pruebas
import { test, expect, describe } from 'vitest';
import { securityFetch, expectUnauthorized } from './helpers';
describe('My Security Test', () => {
test('should reject invalid input', async () => {
const res = await securityFetch('/endpoint', {
method: 'POST',
body: JSON.stringify({ malicious: '<script>alert(1)</script>' })
});
// Test should pass if properly rejected
expect(res.status).toBe(400);
});
});