Última actualización: 17 de Abril de 2026
Versión: 5.0.1
Clasificación: Documento Interno de Seguridad
Auditor: Verificación de Código Actual + Mejoras Implementadas (FASE 1-22)
- OWASP Top 10 - Implementación
- Gestión de Dependencias (pnpm)
- Autenticación y Autorización
- Protección de Datos
- Configuración Segura
- Auditoría y Monitoreo
- Respuesta a Incidentes
- 7 Limiters independientes configurados con diferentes umbrales
- Servicio centralizado
RateLimitingService(253 líneas) - Middleware mejorado
ThrottleRequestsWithRetryAftercon header 429 - IP blocking tras múltiples violaciones
- Listas de excepción inteligentes
Configuración:
API General: 60 reqs/min
Reportes: 5 generaciones/hora
Importaciones: 2/día
Exportaciones: 5/día
Hacienda: 10 envíos/hora
Login: 5 intentos/15 min
Payment: 3 transacciones/hora
- 30+ campos sensibles encriptados automáticamente
- Búsqueda hash-based sin desencriptar datos
- Soporte rotación de claves para cumplimiento normativo
- Control de acceso por IP y rol
- Campos protegidos:
- Usuario: email, teléfono, identificación
- Empresa: CIF, banco, código DANE
- Proveedor: cuenta bancaria
- Transacción: detalles financieros
- Audit trail completo de acceso
- AuditLog Model con 23 columnas
- CRUD automático en todos los modelos
- GDPR/LGPD compliance - Right-to-be-forgotten implementado
- Máscaras automáticas de valores sensibles
- Retención configurable (90 días default)
- Full-text search en cambios de datos
- 13 Scopes para análisis y reporting
- HaciendaComprobante Model con 13 scopes
- Servicios refactorizados:
HaciendaApiClient(HTTP + rate limiting),FirmaDigitalService(XAdES-EPES),OAuthTokenManager(OAuth 2.0),XmlComprobanteBuilder(XML v4.4) - Generador de clave de 50 dígitos (Algoritmo Mod-9)
- Firma digital XAdES-EPES implementada
- 8 endpoints REST para gestión completa
- Estados: pending, signed, sent, accepted, rejected, error
| FASE | Mejora de Seguridad | Impacto |
|---|---|---|
| 4 | PHPStan Level 8 — 0 errores, baseline vacío | Type safety real, eliminados ~2,000 ignores |
| 13 | Eliminación CQRS dead code — 34 archivos | Superficie de ataque reducida |
| 14 | Contract Testing (Pact) + Mutation Testing (Infection) | Verificación de contratos API, calidad de tests |
| 14 | Load Testing (k6) — smoke, carga, detección N+1 | Resiliencia ante picos de tráfico |
| 15 | 11 excepciones de dominio con handler centralizado | Ya NO se expone $e->getMessage() al cliente |
| 15 | ApiResponse trait — envelope unificado | Respuestas consistentes: {success, code, message, data, errors, meta} |
| 16 | BaseService abstracto con hooks tipados | Lógica de negocio aislada de controladores |
| 16 | 63 DTOs con readonly y fromRequest() |
Validación de tipos en capa de transferencia (~65% cobertura) |
| 17 | Rate limiting normalizado + SecurityHeaders middleware | Headers OWASP aplicados globalmente |
| 18 | API Versionado /api/v1/ y /api/v2/ |
Middleware Sunset para deprecación controlada |
| 18.5 | Seeders MasterData/DemoData separados | Datos de producción aislados de datos demo |
| 19.2 | Contract Testing con Pact PHP | Verificación de contratos entre consumidor/proveedor |
| 19.3 | Mutation Testing con Infection PHP | MSI ≥50%, cobertura mutaciones ≥70% |
| 19.4 | CI Pipeline Mejorado (Codecov, PHPStan L8) | 9 workflows CI/CD con umbrales de calidad |
| 19.6 | Hacienda v4.4 — 38/38 brechas cerradas | Compliance normativo 100% |
| 19.7 | PHPStan 0 errores + DTO 65% + DT limpia | Type safety real + factories verificadas |
| 20 | Webhooks + Event-Driven | HMAC-SHA256, SSRF validation, backoff exponencial |
| 21 | Reporting Engine (P&L, Balance, KPIs) | Reportes financieros + exportación PDF/Excel/CSV |
| 22 | Escalabilidad (Read Replicas, Horizon, ETag, Tracing) | OpenTelemetry, ETags 304, distributed tracing |
Resultado acumulado: 1270+ tests passing, PHPStan L8 0 errors, 9 workflows CI/CD, 80 policies RBAC.
Estado: IMPLEMENTADO
Medidas aplicadas:
- Policies Laravel: 80+ políticas de autorización implementadas
- Multi-tenancy: Aislamiento completo de datos por empresa
- Middleware:
EmpresaMiddlewarepara validación de contexto - Scopes globales:
EmpresaScopeaplicado automáticamente a queries
// Ejemplo de protección en controladores
public function show(Factura $factura): JsonResponse
{
$this->authorize('view', $factura); // Policy check
// ...
}Archivos clave:
app/Policies/*- 80+ archivos de políticasapp/Models/Scopes/EmpresaScope.phpapp/Http/Middleware/EmpresaMiddleware.php
Estado: IMPLEMENTADO
Medidas aplicadas:
- Contraseñas: Bcrypt con cost factor 12
- Tokens: Laravel Sanctum con tokens SHA-256
- Certificados: XAdES-EPES para firma digital
- TLS: Forzado en producción (HTTPS)
- Datos sensibles: Encriptados con APP_KEY
// Configuración de encriptación
'cipher' => 'AES-256-CBC',
'key' => env('APP_KEY'), // 256-bit keyVariables de entorno sensibles:
APP_KEY=base64:... # Clave de encriptación
DB_PASSWORD=... # Nunca en código
HACIENDA_P12_PASSWORD=... # Certificado digitalEstado: IMPLEMENTADO
Medidas aplicadas:
- SQL Injection: Eloquent ORM con bindings
- XSS: Blade escaping automático
- Command Injection:
shell_exec()presente SOLO enFirmaDigitalService::convertirP12Legacy()conescapeshellarg()estricto (conversión de certificados .p12 legacy).HealthCheckControllerya NO usashell_exec()(resuelto DT-7). - LDAP Injection: No aplica
// ✅ Seguro - Eloquent con bindings
$productos = Producto::where('nombre', 'like', "%{$search}%")->get();
// ❌ NUNCA hacer esto
// DB::raw("SELECT * FROM productos WHERE nombre = '$search'");FormRequest Validation:
public function rules(): array
{
return [
'email' => ['required', 'email:rfc,dns'],
'codigo' => ['required', 'string', 'max:50', 'regex:/^[A-Z0-9-]+$/'],
];
}Estado: IMPLEMENTADO
Medidas aplicadas:
- Arquitectura: Separación de capas (Controllers → Services → DTOs → Models)
- BaseService abstracto: Hooks tipados (beforeCreate, afterCreate, applyFilters) — FASE 16
- 63 DTOs con propiedades
readonlyy factoryfromRequest()— FASES 16-19.7 (~65% cobertura) - 11 excepciones de dominio con handler centralizado — FASE 15
- ApiResponse trait: Envelope unificado, sin exposición de errores internos — FASE 15
- 170+ FormRequests con validación comprehensiva
- Rate Limiting: 7 limitadores granulares por contexto
// Rate limiting configurado
Route::middleware(['throttle:api'])->group(function () {
// 60 requests por minuto por defecto
});
Route::middleware(['throttle:login'])->post('/login', ...);
// 5 intentos por minutoEstado: IMPLEMENTADO
Medidas aplicadas:
- DEBUG: Deshabilitado en producción
- Headers: Configurados correctamente
- CORS: Restrictivo por defecto
- Error Messages: Genéricos en producción
// config/app.php
'debug' => env('APP_DEBUG', false),
// config/cors.php
'allowed_origins' => explode(',', env('CORS_ALLOWED_ORIGINS', '')),Headers de seguridad recomendados (nginx):
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;Estado: IMPLEMENTADO
Medidas aplicadas:
- pnpm: Gestor de paquetes seguro (no npm)
- Composer audit: Verificación de vulnerabilidades
- Dependabot: Alertas automáticas en GitHub
- Actualizaciones: Proceso regular de actualización
# Auditoría de seguridad
composer audit
pnpm audit
# Actualización segura
composer update --with-all-dependencies
pnpm update --latestEstado: IMPLEMENTADO
Medidas aplicadas:
- Laravel Sanctum: Tokens seguros para API
- Password Policy: Mínimo 8 caracteres, complejidad
- Session Management: Tokens con expiración
- Multi-factor: Preparado para implementar
// config/sanctum.php
'expiration' => 60 * 24, // 24 horas
// Validación de contraseñas
'password' => ['required', Password::min(8)->mixedCase()->numbers()],Estado: IMPLEMENTADO
Medidas aplicadas:
- pnpm lockfile: Integridad verificada
- Composer.lock: Versiones fijadas
- CI/CD: Pipeline seguro
- Firma digital: XAdES-EPES para facturas
# pnpm verifica integridad automáticamente
pnpm install --frozen-lockfileEstado: IMPLEMENTADO
Medidas aplicadas:
- Laravel Logging: Configurado para producción
- Sentry: Monitoreo de errores
- Audit Trail: Registros de cambios
- Activity Log: Acciones de usuario
// config/logging.php
'channels' => [
'stack' => [
'channels' => ['daily', 'sentry'],
],
],Estado: IMPLEMENTADO
Medidas aplicadas:
- URLs validadas: Solo dominios permitidos
- Timeout: Configurado en requests externos
- Hacienda API: URLs fijas, no dinámicas
// Solo URLs de Hacienda permitidas
private const HACIENDA_URLS = [
'production' => 'https://api.comprobanteselectronicos.go.cr',
'sandbox' => 'https://api-sandbox.comprobanteselectronicos.go.cr',
];| Característica | npm | pnpm |
|---|---|---|
| Almacenamiento | Duplicados | Content-addressable |
| Velocidad | Lento | 2-3x más rápido |
| Seguridad | Vulnerable a supply chain | Mejor aislamiento |
| Integridad | Básica | Verificación estricta |
| Espacio en disco | Alto | Mínimo |
# Instalación global
npm install -g pnpm
# O con corepack (recomendado)
corepack enable
corepack prepare pnpm@latest --activate
# Verificar instalación
pnpm --version# Auditoría de vulnerabilidades
pnpm audit
# Actualizar con parches de seguridad
pnpm update --latest
# Verificar integridad del lockfile
pnpm install --frozen-lockfile
# Listar dependencias outdated
pnpm outdated# Usar pnpm exclusivamente
only-allow-pnpm=true
# Verificar integridad
verify-store-integrity=true
# Auditoría automática
audit=true// Protección de rutas API
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('facturas', FacturaController::class);
});// Autorización granular
class FacturaPolicy
{
public function view(User $user, Factura $factura): bool
{
return $user->empresa_id === $factura->empresa_id;
}
}El sistema implementa RBAC (Role-Based Access Control) con 68 permisos y 8 roles:
- Administrador: Acceso total al sistema
- Gerente: Gestión de su empresa (ventas, compras, reportes)
- Contador: Contabilidad, nómina, declaraciones tributarias
- Vendedor: Ventas, clientes, productos
- Bodeguero: Inventario, almacenes, movimientos
- Cajero: Caja, cobros, pagos
- RRHH: Empleados, nómina, períodos
- Auditor: Lectura de auditoría, logs, compliance
80+ policies con BasePolicy compartida, doble capa (middleware permission:X + Policy).
- TLS 1.3 obligatorio en producción
- HSTS habilitado
- Certificados válidos
- Encriptación AES-256
- Hashing Bcrypt para contraseñas
- Backups encriptados
// Modelo con campos ocultos
protected $hidden = [
'password',
'remember_token',
'p12_password',
];
// Campos encriptados
protected $casts = [
'password' => 'hashed',
'datos_sensibles' => 'encrypted',
];# Producción
APP_ENV=production
APP_DEBUG=false
APP_URL=https://api.tudominio.com
# Base de datos
DB_CONNECTION=mysql
DB_HOST=127.0.0.1 # No exponer externamente
# Cache y sesiones
SESSION_DRIVER=redis
CACHE_DRIVER=redis
# Logging
LOG_CHANNEL=stack
LOG_LEVEL=warning// Middleware de seguridad recomendado
public function handle($request, $next)
{
$response = $next($request);
return $response
->header('X-Frame-Options', 'DENY')
->header('X-Content-Type-Options', 'nosniff')
->header('X-XSS-Protection', '1; mode=block')
->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}// Registrar eventos importantes
Log::channel('security')->info('Login exitoso', [
'user_id' => $user->id,
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
]);- Intentos de login fallidos (> 5)
- Acceso denegado repetido
- Cambios en roles/permisos
- Errores 500 en producción
// config/sentry.php
'dsn' => env('SENTRY_LARAVEL_DSN'),
'traces_sample_rate' => 0.2,- Detección: Monitoreo automático + reportes
- Contención: Aislar el problema
- Erradicación: Eliminar la causa
- Recuperación: Restaurar operaciones
- Lecciones: Documentar y mejorar
Email: [email protected]
- Identificar alcance
- Notificar equipo
- Preservar evidencia
- Contener amenaza
- Comunicar a afectados
- Documentar timeline
- Implementar mejoras
Si encuentras una vulnerabilidad de seguridad:
- NO publiques públicamente
- Envía email a:
[email protected] - Incluye:
- Descripción detallada
- Pasos para reproducir
- Impacto potencial
- Sugerencia de fix (opcional)
Respondemos en máximo 48 horas hábiles.
- APP_DEBUG=false
- APP_ENV=production
- HTTPS configurado
- Firewall activo
- Base de datos no expuesta
- Redis protegido
- Logs configurados
- Backups automáticos
- Monitoreo activo
- Verificar headers de seguridad
- Probar autenticación
- Verificar rate limiting
- Revisar logs por errores
- Confirmar SSL/TLS
| Métrica | Valor |
|---|---|
| PHPStan | Level 8, 0 errores |
| Tests | 997 passing (100%) |
| OWASP Top 10 | 10/10 cubiertos |
| Políticas RBAC | 80+ |
| Campos encriptados | 30+ (AES-256-CBC) |
| Rate limiters | 7 independientes |
| Security headers | 8 (OWASP compliant) |
| CI/CD workflows | 7 (incluye quality gates) |
| Excepciones dominio | 11 tipadas con handler |
| Contract tests | 6 (Pact PHP) |
| Mutation testing | MSI ≥ 50%, Covered ≥ 70% |
Documento mantenido por Senselab — Actualizado v4.2.0, 10 de abril de 2026