mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
feat: add laravel skills (#420)
* feat: add laravel skills * docs: fix laravel patterns example * docs: add laravel api example * docs: update readme and configure-ecc for laravel skills * docs: reference laravel skills in php rules * docs: add php import guidance * docs: expand laravel skills with more pattern, security, testing, and verification examples * docs: add laravel routing, security, testing, and sail guidance * docs: fix laravel example issues from code review * docs: fix laravel examples and skills per review findings * docs: resolve remaining laravel review fixes * docs: refine laravel patterns and tdd guidance * docs: clarify laravel queue healthcheck guidance * docs: fix laravel examples and test guidance * docs: correct laravel tdd and api example details * docs: align laravel form request auth semantics * docs: fix laravel coverage, imports, and scope guidance * docs: align laravel tdd and security examples with guidance * docs: tighten laravel form request authorization examples * docs: fix laravel tdd and queue job examples * docs: harden laravel rate limiting and policy examples * docs: fix laravel pagination, validation, and verification examples * docs: align laravel controller response with envelope * docs: strengthen laravel password validation example * docs: address feedback regarding examples * docs: improve guidance and examples for pest usage * docs: clarify laravel upload storage and authorization notes * docs: tighten up examples
This commit is contained in:
285
skills/laravel-security/SKILL.md
Normal file
285
skills/laravel-security/SKILL.md
Normal file
@@ -0,0 +1,285 @@
|
||||
---
|
||||
name: laravel-security
|
||||
description: Laravel security best practices for authn/authz, validation, CSRF, mass assignment, file uploads, secrets, rate limiting, and secure deployment.
|
||||
origin: ECC
|
||||
---
|
||||
|
||||
# Laravel Security Best Practices
|
||||
|
||||
Comprehensive security guidance for Laravel applications to protect against common vulnerabilities.
|
||||
|
||||
## When to Activate
|
||||
|
||||
- Adding authentication or authorization
|
||||
- Handling user input and file uploads
|
||||
- Building new API endpoints
|
||||
- Managing secrets and environment settings
|
||||
- Hardening production deployments
|
||||
|
||||
## How It Works
|
||||
|
||||
- Middleware provides baseline protections (CSRF via `VerifyCsrfToken`, security headers via `SecurityHeaders`).
|
||||
- Guards and policies enforce access control (`auth:sanctum`, `$this->authorize`, policy middleware).
|
||||
- Form Requests validate and shape input (`UploadInvoiceRequest`) before it reaches services.
|
||||
- Rate limiting adds abuse protection (`RateLimiter::for('login')`) alongside auth controls.
|
||||
- Data safety comes from encrypted casts, mass-assignment guards, and signed routes (`URL::temporarySignedRoute` + `signed` middleware).
|
||||
|
||||
## Core Security Settings
|
||||
|
||||
- `APP_DEBUG=false` in production
|
||||
- `APP_KEY` must be set and rotated on compromise
|
||||
- Set `SESSION_SECURE_COOKIE=true` and `SESSION_SAME_SITE=lax` (or `strict` for sensitive apps)
|
||||
- Configure trusted proxies for correct HTTPS detection
|
||||
|
||||
## Session and Cookie Hardening
|
||||
|
||||
- Set `SESSION_HTTP_ONLY=true` to prevent JavaScript access
|
||||
- Use `SESSION_SAME_SITE=strict` for high-risk flows
|
||||
- Regenerate sessions on login and privilege changes
|
||||
|
||||
## Authentication and Tokens
|
||||
|
||||
- Use Laravel Sanctum or Passport for API auth
|
||||
- Prefer short-lived tokens with refresh flows for sensitive data
|
||||
- Revoke tokens on logout and compromised accounts
|
||||
|
||||
Example route protection:
|
||||
|
||||
```php
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::middleware('auth:sanctum')->get('/me', function (Request $request) {
|
||||
return $request->user();
|
||||
});
|
||||
```
|
||||
|
||||
## Password Security
|
||||
|
||||
- Hash passwords with `Hash::make()` and never store plaintext
|
||||
- Use Laravel's password broker for reset flows
|
||||
|
||||
```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'])]);
|
||||
```
|
||||
|
||||
## Authorization: Policies and Gates
|
||||
|
||||
- Use policies for model-level authorization
|
||||
- Enforce authorization in controllers and services
|
||||
|
||||
```php
|
||||
$this->authorize('update', $project);
|
||||
```
|
||||
|
||||
Use policy middleware for route-level enforcement:
|
||||
|
||||
```php
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::put('/projects/{project}', [ProjectController::class, 'update'])
|
||||
->middleware(['auth:sanctum', 'can:update,project']);
|
||||
```
|
||||
|
||||
## Validation and Data Sanitization
|
||||
|
||||
- Always validate inputs with Form Requests
|
||||
- Use strict validation rules and type checks
|
||||
- Never trust request payloads for derived fields
|
||||
|
||||
## Mass Assignment Protection
|
||||
|
||||
- Use `$fillable` or `$guarded` and avoid `Model::unguard()`
|
||||
- Prefer DTOs or explicit attribute mapping
|
||||
|
||||
## SQL Injection Prevention
|
||||
|
||||
- Use Eloquent or query builder parameter binding
|
||||
- Avoid raw SQL unless strictly necessary
|
||||
|
||||
```php
|
||||
DB::select('select * from users where email = ?', [$email]);
|
||||
```
|
||||
|
||||
## XSS Prevention
|
||||
|
||||
- Blade escapes output by default (`{{ }}`)
|
||||
- Use `{!! !!}` only for trusted, sanitized HTML
|
||||
- Sanitize rich text with a dedicated library
|
||||
|
||||
## CSRF Protection
|
||||
|
||||
- Keep `VerifyCsrfToken` middleware enabled
|
||||
- Include `@csrf` in forms and send XSRF tokens for SPA requests
|
||||
|
||||
For SPA authentication with Sanctum, ensure stateful requests are configured:
|
||||
|
||||
```php
|
||||
// config/sanctum.php
|
||||
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost')),
|
||||
```
|
||||
|
||||
## File Upload Safety
|
||||
|
||||
- Validate file size, MIME type, and extension
|
||||
- Store uploads outside the public path when possible
|
||||
- Scan files for malware if required
|
||||
|
||||
```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') // set this to a non-public disk
|
||||
);
|
||||
```
|
||||
|
||||
## Rate Limiting
|
||||
|
||||
- Apply `throttle` middleware on auth and write endpoints
|
||||
- Use stricter limits for login, password reset, and 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'))),
|
||||
];
|
||||
});
|
||||
```
|
||||
|
||||
## Secrets and Credentials
|
||||
|
||||
- Never commit secrets to source control
|
||||
- Use environment variables and secret managers
|
||||
- Rotate keys after exposure and invalidate sessions
|
||||
|
||||
## Encrypted Attributes
|
||||
|
||||
Use encrypted casts for sensitive columns at rest.
|
||||
|
||||
```php
|
||||
protected $casts = [
|
||||
'api_token' => 'encrypted',
|
||||
];
|
||||
```
|
||||
|
||||
## Security Headers
|
||||
|
||||
- Add CSP, HSTS, and frame protection where appropriate
|
||||
- Use trusted proxy configuration to enforce HTTPS redirects
|
||||
|
||||
Example middleware to set headers:
|
||||
|
||||
```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', // add includeSubDomains/preload only when all subdomains are HTTPS
|
||||
'X-Frame-Options' => 'DENY',
|
||||
'X-Content-Type-Options' => 'nosniff',
|
||||
'Referrer-Policy' => 'no-referrer',
|
||||
]);
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## CORS and API Exposure
|
||||
|
||||
- Restrict origins in `config/cors.php`
|
||||
- Avoid wildcard origins for authenticated routes
|
||||
|
||||
```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 and PII
|
||||
|
||||
- Never log passwords, tokens, or full card data
|
||||
- Redact sensitive fields in structured logs
|
||||
|
||||
```php
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
Log::info('User updated profile', [
|
||||
'user_id' => $user->id,
|
||||
'email' => '[REDACTED]',
|
||||
'token' => '[REDACTED]',
|
||||
]);
|
||||
```
|
||||
|
||||
## Dependency Security
|
||||
|
||||
- Run `composer audit` regularly
|
||||
- Pin dependencies with care and update promptly on CVEs
|
||||
|
||||
## Signed URLs
|
||||
|
||||
Use signed routes for temporary, tamper-proof links.
|
||||
|
||||
```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');
|
||||
```
|
||||
Reference in New Issue
Block a user