mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-14 12:11:27 +08:00
ac0f11c640
Adds a complete Spanish translation of the ECC documentation under docs/es/, mirroring the Turkish (docs/tr/) translation in scope. 141 files covering agents, commands, rules, skills, contexts, examples, and core docs. Updates root README.md with the Spanish language link. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
286 lines
8.1 KiB
Markdown
286 lines
8.1 KiB
Markdown
---
|
|
name: laravel-security
|
|
description: Buenas prácticas de seguridad en Laravel para autenticación/autorización, validación, CSRF, asignación masiva, subida de archivos, secretos, limitación de velocidad y despliegue seguro.
|
|
origin: ECC
|
|
---
|
|
|
|
# Buenas Prácticas de Seguridad en Laravel
|
|
|
|
Guía completa de seguridad para aplicaciones Laravel que protege contra vulnerabilidades comunes.
|
|
|
|
## Cuándo Activar
|
|
|
|
- Agregar autenticación o autorización
|
|
- Manejar entrada de usuarios y subida de archivos
|
|
- Construir nuevos endpoints de API
|
|
- Gestionar secretos y configuración de entornos
|
|
- Reforzar despliegues en producción
|
|
|
|
## Cómo Funciona
|
|
|
|
- El middleware proporciona protecciones de base (CSRF mediante `VerifyCsrfToken`, cabeceras de seguridad mediante `SecurityHeaders`).
|
|
- Los guards y policies aplican el control de acceso (`auth:sanctum`, `$this->authorize`, middleware de policy).
|
|
- Los Form Requests validan y dan forma a la entrada (`UploadInvoiceRequest`) antes de que llegue a los servicios.
|
|
- La limitación de velocidad agrega protección contra abusos (`RateLimiter::for('login')`) junto con controles de autenticación.
|
|
- La seguridad de datos proviene de casts encriptados, guards de asignación masiva y rutas firmadas (`URL::temporarySignedRoute` + middleware `signed`).
|
|
|
|
## Configuración Principal de Seguridad
|
|
|
|
- `APP_DEBUG=false` en producción
|
|
- `APP_KEY` debe estar establecido y rotarse al comprometerse
|
|
- Establecer `SESSION_SECURE_COOKIE=true` y `SESSION_SAME_SITE=lax` (o `strict` para apps sensibles)
|
|
- Configurar proxies de confianza para la detección correcta de HTTPS
|
|
|
|
## Reforzamiento de Sesión y Cookies
|
|
|
|
- Establecer `SESSION_HTTP_ONLY=true` para prevenir acceso desde JavaScript
|
|
- Usar `SESSION_SAME_SITE=strict` para flujos de alto riesgo
|
|
- Regenerar sesiones al iniciar sesión y al cambiar privilegios
|
|
|
|
## Autenticación y Tokens
|
|
|
|
- Usar Laravel Sanctum o Passport para autenticación de API
|
|
- Preferir tokens de corta vida con flujos de actualización para datos sensibles
|
|
- Revocar tokens al cerrar sesión y en cuentas comprometidas
|
|
|
|
Ejemplo de protección de rutas:
|
|
|
|
```php
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
Route::middleware('auth:sanctum')->get('/me', function (Request $request) {
|
|
return $request->user();
|
|
});
|
|
```
|
|
|
|
## Seguridad de Contraseñas
|
|
|
|
- Hashear contraseñas con `Hash::make()` y nunca almacenar texto plano
|
|
- Usar el password broker de Laravel para los flujos de restablecimiento
|
|
|
|
```php
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Validation\Rules\Password;
|
|
|
|
$validated = $request->validate([
|
|
'password' => ['required', 'string', Password::min(12)->letters()->mixedCase()->numbers()->symbols()],
|
|
]);
|
|
|
|
$user->update(['password' => Hash::make($validated['password'])]);
|
|
```
|
|
|
|
## Autorización: Policies y Gates
|
|
|
|
- Usar policies para autorización a nivel de modelo
|
|
- Aplicar autorización en controladores y servicios
|
|
|
|
```php
|
|
$this->authorize('update', $project);
|
|
```
|
|
|
|
Usar middleware de policy para aplicación a nivel de ruta:
|
|
|
|
```php
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
Route::put('/projects/{project}', [ProjectController::class, 'update'])
|
|
->middleware(['auth:sanctum', 'can:update,project']);
|
|
```
|
|
|
|
## Validación y Sanitización de Datos
|
|
|
|
- Siempre validar entradas con Form Requests
|
|
- Usar reglas de validación estrictas y verificaciones de tipo
|
|
- Nunca confiar en los payloads de la request para campos derivados
|
|
|
|
## Protección contra Asignación Masiva
|
|
|
|
- Usar `$fillable` o `$guarded` y evitar `Model::unguard()`
|
|
- Preferir DTOs o mapeo explícito de atributos
|
|
|
|
## Prevención de Inyección SQL
|
|
|
|
- Usar Eloquent o el query builder con binding de parámetros
|
|
- Evitar SQL crudo a menos que sea estrictamente necesario
|
|
|
|
```php
|
|
DB::select('select * from users where email = ?', [$email]);
|
|
```
|
|
|
|
## Prevención de XSS
|
|
|
|
- Blade escapa la salida por defecto (`{{ }}`)
|
|
- Usar `{!! !!}` solo para HTML de confianza y sanitizado
|
|
- Sanitizar texto enriquecido con una librería dedicada
|
|
|
|
## Protección CSRF
|
|
|
|
- Mantener el middleware `VerifyCsrfToken` habilitado
|
|
- Incluir `@csrf` en formularios y enviar tokens XSRF en requests de SPA
|
|
|
|
Para autenticación SPA con Sanctum, asegurarse de que las requests stateful estén configuradas:
|
|
|
|
```php
|
|
// config/sanctum.php
|
|
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost')),
|
|
```
|
|
|
|
## Seguridad en Subida de Archivos
|
|
|
|
- Validar tamaño de archivo, tipo MIME y extensión
|
|
- Almacenar subidas fuera del directorio público cuando sea posible
|
|
- Escanear archivos en busca de malware si es necesario
|
|
|
|
```php
|
|
final class UploadInvoiceRequest extends FormRequest
|
|
{
|
|
public function authorize(): bool
|
|
{
|
|
return (bool) $this->user()?->can('upload-invoice');
|
|
}
|
|
|
|
public function rules(): array
|
|
{
|
|
return [
|
|
'invoice' => ['required', 'file', 'mimes:pdf', 'max:5120'],
|
|
];
|
|
}
|
|
}
|
|
```
|
|
|
|
```php
|
|
$path = $request->file('invoice')->store(
|
|
'invoices',
|
|
config('filesystems.private_disk', 'local') // establecer a un disco no público
|
|
);
|
|
```
|
|
|
|
## Limitación de Velocidad
|
|
|
|
- Aplicar middleware `throttle` en endpoints de autenticación y escritura
|
|
- Usar límites más estrictos para login, restablecimiento de contraseña y OTP
|
|
|
|
```php
|
|
use Illuminate\Cache\RateLimiting\Limit;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
|
|
RateLimiter::for('login', function (Request $request) {
|
|
return [
|
|
Limit::perMinute(5)->by($request->ip()),
|
|
Limit::perMinute(5)->by(strtolower((string) $request->input('email'))),
|
|
];
|
|
});
|
|
```
|
|
|
|
## Secretos y Credenciales
|
|
|
|
- Nunca hacer commit de secretos al control de versiones
|
|
- Usar variables de entorno y gestores de secretos
|
|
- Rotar claves después de una exposición e invalidar sesiones
|
|
|
|
## Atributos Encriptados
|
|
|
|
Usar casts encriptados para columnas sensibles en reposo.
|
|
|
|
```php
|
|
protected $casts = [
|
|
'api_token' => 'encrypted',
|
|
];
|
|
```
|
|
|
|
## Cabeceras de Seguridad
|
|
|
|
- Agregar CSP, HSTS y protección de frames donde sea apropiado
|
|
- Usar configuración de proxies de confianza para forzar redirecciones HTTPS
|
|
|
|
Ejemplo de middleware para establecer cabeceras:
|
|
|
|
```php
|
|
use Illuminate\Http\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
final class SecurityHeaders
|
|
{
|
|
public function handle(Request $request, \Closure $next): Response
|
|
{
|
|
$response = $next($request);
|
|
|
|
$response->headers->add([
|
|
'Content-Security-Policy' => "default-src 'self'",
|
|
'Strict-Transport-Security' => 'max-age=31536000', // agregar includeSubDomains/preload solo cuando todos los subdominios sean HTTPS
|
|
'X-Frame-Options' => 'DENY',
|
|
'X-Content-Type-Options' => 'nosniff',
|
|
'Referrer-Policy' => 'no-referrer',
|
|
]);
|
|
|
|
return $response;
|
|
}
|
|
}
|
|
```
|
|
|
|
## CORS y Exposición de API
|
|
|
|
- Restringir orígenes en `config/cors.php`
|
|
- Evitar orígenes wildcard para rutas autenticadas
|
|
|
|
```php
|
|
// config/cors.php
|
|
return [
|
|
'paths' => ['api/*', 'sanctum/csrf-cookie'],
|
|
'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
|
'allowed_origins' => ['https://app.example.com'],
|
|
'allowed_headers' => [
|
|
'Content-Type',
|
|
'Authorization',
|
|
'X-Requested-With',
|
|
'X-XSRF-TOKEN',
|
|
'X-CSRF-TOKEN',
|
|
],
|
|
'supports_credentials' => true,
|
|
];
|
|
```
|
|
|
|
## Logging y PII
|
|
|
|
- Nunca registrar contraseñas, tokens o datos completos de tarjetas
|
|
- Redactar campos sensibles en logs estructurados
|
|
|
|
```php
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
Log::info('User updated profile', [
|
|
'user_id' => $user->id,
|
|
'email' => '[REDACTED]',
|
|
'token' => '[REDACTED]',
|
|
]);
|
|
```
|
|
|
|
## Seguridad de Dependencias
|
|
|
|
- Ejecutar `composer audit` regularmente
|
|
- Fijar dependencias con cuidado y actualizar rápidamente ante CVEs
|
|
|
|
## URLs Firmadas
|
|
|
|
Usar rutas firmadas para enlaces temporales a prueba de manipulaciones.
|
|
|
|
```php
|
|
use Illuminate\Support\Facades\URL;
|
|
|
|
$url = URL::temporarySignedRoute(
|
|
'downloads.invoice',
|
|
now()->addMinutes(15),
|
|
['invoice' => $invoice->id]
|
|
);
|
|
```
|
|
|
|
```php
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
Route::get('/invoices/{invoice}/download', [InvoiceController::class, 'download'])
|
|
->name('downloads.invoice')
|
|
->middleware('signed');
|
|
```
|