- Add comprehensive health check system with multiple endpoints - Add Prometheus metrics endpoint - Add production logging configurations (5 strategies) - Add complete deployment documentation suite: * QUICKSTART.md - 30-minute deployment guide * DEPLOYMENT_CHECKLIST.md - Printable verification checklist * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference * production-logging.md - Logging configuration guide * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation * README.md - Navigation hub * DEPLOYMENT_SUMMARY.md - Executive summary - Add deployment scripts and automation - Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment - Update README with production-ready features All production infrastructure is now complete and ready for deployment.
865 lines
20 KiB
Markdown
865 lines
20 KiB
Markdown
# LiveComponents Security E2E Tests
|
|
|
|
Comprehensive security testing suite for LiveComponents framework covering CSRF protection, rate limiting, idempotency, input sanitization, authorization, and session security.
|
|
|
|
## Overview
|
|
|
|
This test suite validates critical security features:
|
|
- **CSRF Protection**: Token validation for state-changing actions
|
|
- **Rate Limiting**: Protection against abuse and DoS attacks
|
|
- **Idempotency**: Preventing duplicate action execution
|
|
- **Input Sanitization**: XSS and injection prevention
|
|
- **Authorization**: Access control and permissions
|
|
- **Session Security**: Session management and hijacking prevention
|
|
- **Content Security Policy**: CSP header enforcement
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
```bash
|
|
# Ensure Playwright is installed
|
|
npm install
|
|
|
|
# Install browser binaries
|
|
npx playwright install chromium
|
|
|
|
# Ensure development server is running
|
|
make up
|
|
```
|
|
|
|
### Running Security Tests
|
|
|
|
```bash
|
|
# Run all security tests
|
|
npm run test:security
|
|
|
|
# Run specific security test category
|
|
npx playwright test security.spec.js --grep "CSRF Protection"
|
|
npx playwright test security.spec.js --grep "Rate Limiting"
|
|
npx playwright test security.spec.js --grep "Idempotency"
|
|
|
|
# Run with visible browser (for debugging)
|
|
npm run test:security:headed
|
|
|
|
# Run with debug mode
|
|
npm run test:security:debug
|
|
```
|
|
|
|
## Test Categories
|
|
|
|
### 1. CSRF Protection (4 tests)
|
|
|
|
**Purpose:** Validate Cross-Site Request Forgery protection for all state-changing actions.
|
|
|
|
#### Test: CSRF token included in requests
|
|
|
|
**Validates:**
|
|
- CSRF token present in action requests
|
|
- Token included in headers (`X-CSRF-Token`) or POST data (`_csrf_token`)
|
|
- Framework automatically handles token management
|
|
|
|
**Expected Behavior:**
|
|
```javascript
|
|
// Request includes CSRF token
|
|
headers: {
|
|
'X-CSRF-Token': 'generated-token-value'
|
|
}
|
|
|
|
// OR in POST data
|
|
{
|
|
_csrf_token: 'generated-token-value',
|
|
action: 'increment',
|
|
params: { ... }
|
|
}
|
|
```
|
|
|
|
#### Test: Reject action without CSRF token
|
|
|
|
**Validates:**
|
|
- Requests without CSRF token are rejected
|
|
- Appropriate error message returned
|
|
- No state changes occur
|
|
|
|
**Expected Response:**
|
|
```
|
|
Status: 403 Forbidden
|
|
Error: "CSRF token validation failed"
|
|
```
|
|
|
|
#### Test: Reject action with invalid CSRF token
|
|
|
|
**Validates:**
|
|
- Invalid/expired tokens are rejected
|
|
- Token tampering detected
|
|
- Security event logged
|
|
|
|
**Test Approach:**
|
|
```javascript
|
|
// Replace token with invalid value
|
|
headers: { 'X-CSRF-Token': 'invalid-token-12345' }
|
|
|
|
// Expected: 403 Forbidden
|
|
```
|
|
|
|
#### Test: CSRF token rotation
|
|
|
|
**Validates:**
|
|
- Tokens rotate after usage (optional, framework-dependent)
|
|
- New token provided in response
|
|
- Old token invalidated
|
|
|
|
**Rotation Strategy:**
|
|
- **Per-request rotation**: New token after each action
|
|
- **Time-based rotation**: New token after TTL
|
|
- **Session-based**: Token tied to session lifetime
|
|
|
|
### 2. Rate Limiting (5 tests)
|
|
|
|
**Purpose:** Prevent abuse through excessive action calls and DoS attacks.
|
|
|
|
#### Test: Enforce rate limit on rapid calls
|
|
|
|
**Configuration:**
|
|
- **Default Limit**: 10 requests per minute
|
|
- **Window**: 60 seconds sliding window
|
|
- **Action**: Block excess requests
|
|
|
|
**Test Approach:**
|
|
```javascript
|
|
// Trigger 20 rapid action calls
|
|
for (let i = 0; i < 20; i++) {
|
|
await triggerAction();
|
|
}
|
|
|
|
// Expected: First 10 succeed, remaining 10 blocked
|
|
// Success rate: 50% (10/20)
|
|
```
|
|
|
|
**Expected Error:**
|
|
```
|
|
Status: 429 Too Many Requests
|
|
Error: "Rate limit exceeded"
|
|
Retry-After: 45 // seconds
|
|
```
|
|
|
|
#### Test: Retry-After header
|
|
|
|
**Validates:**
|
|
- `Retry-After` header present in 429 responses
|
|
- Header contains remaining cooldown time
|
|
- Client can use header for backoff
|
|
|
|
**Response Format:**
|
|
```http
|
|
HTTP/1.1 429 Too Many Requests
|
|
Retry-After: 60
|
|
Content-Type: application/json
|
|
|
|
```
|
|
|
|
#### Test: Rate limit reset after cooldown
|
|
|
|
**Validates:**
|
|
- Rate limit resets after window expires
|
|
- Actions allowed again after cooldown
|
|
- No lingering restrictions
|
|
|
|
**Timeline:**
|
|
```
|
|
00:00 - First 10 requests succeed
|
|
00:01 - Next 10 requests blocked (rate limited)
|
|
00:01 - Retry-After: 59 seconds
|
|
01:00 - Window expires, limit resets
|
|
01:01 - New requests succeed
|
|
```
|
|
|
|
#### Test: Separate limits per action type
|
|
|
|
**Validates:**
|
|
- Different actions have independent rate limits
|
|
- Hitting limit on action A doesn't affect action B
|
|
- Granular control per action
|
|
|
|
**Configuration:**
|
|
```javascript
|
|
const RATE_LIMITS = {
|
|
'increment': { limit: 10, window: 60 },
|
|
'delete': { limit: 5, window: 300 },
|
|
'search': { limit: 30, window: 60 }
|
|
};
|
|
```
|
|
|
|
#### Test: IP-based rate limiting
|
|
|
|
**Validates:**
|
|
- Rate limits applied per IP address
|
|
- Multiple users from same IP share limit
|
|
- Different IPs have independent limits
|
|
|
|
**Scenario:**
|
|
```
|
|
User A (IP: 192.168.1.1) - 10 requests
|
|
User B (IP: 192.168.1.1) - 10 requests
|
|
Result: Both users share 10-request limit for that IP
|
|
```
|
|
|
|
### 3. Idempotency (4 tests)
|
|
|
|
**Purpose:** Ensure critical operations execute exactly once, even with duplicate requests.
|
|
|
|
#### Test: Handle duplicate calls idempotently
|
|
|
|
**Validates:**
|
|
- Duplicate action calls with same idempotency key are ignored
|
|
- Operation executes exactly once
|
|
- State changes applied only once
|
|
|
|
**Test Approach:**
|
|
```javascript
|
|
// First call with idempotency key
|
|
await callAction('increment', { idempotencyKey: 'key-123' });
|
|
// Counter: 0 → 1
|
|
|
|
// Duplicate call (same key)
|
|
await callAction('increment', { idempotencyKey: 'key-123' });
|
|
// Counter: 1 (unchanged, duplicate ignored)
|
|
```
|
|
|
|
#### Test: Allow different idempotency keys
|
|
|
|
**Validates:**
|
|
- Different idempotency keys allow separate executions
|
|
- Each unique key represents distinct operation
|
|
- No interference between different keys
|
|
|
|
**Test Approach:**
|
|
```javascript
|
|
await callAction('increment', { idempotencyKey: 'key-1' }); // Executes
|
|
await callAction('increment', { idempotencyKey: 'key-2' }); // Executes
|
|
await callAction('increment', { idempotencyKey: 'key-1' }); // Ignored (duplicate)
|
|
```
|
|
|
|
#### Test: Idempotency key expiration
|
|
|
|
**Validates:**
|
|
- Keys expire after TTL (default: 24 hours)
|
|
- Expired keys allow re-execution
|
|
- Storage cleanup for old keys
|
|
|
|
**Timeline:**
|
|
```
|
|
00:00 - Action with key-123 executes
|
|
00:00 - Duplicate with key-123 ignored
|
|
24:00 - Key-123 expires
|
|
24:01 - Action with key-123 executes again (new operation)
|
|
```
|
|
|
|
#### Test: Cached result for duplicate action
|
|
|
|
**Validates:**
|
|
- Duplicate calls return cached result
|
|
- No server-side re-execution
|
|
- Consistent response for same key
|
|
|
|
**Expected Behavior:**
|
|
```javascript
|
|
const result1 = await callAction('createOrder', {
|
|
idempotencyKey: 'order-123'
|
|
});
|
|
// Returns: { orderId: 'abc', total: 100 }
|
|
|
|
const result2 = await callAction('createOrder', {
|
|
idempotencyKey: 'order-123'
|
|
});
|
|
// Returns: { orderId: 'abc', total: 100 } (cached, same result)
|
|
```
|
|
|
|
### 4. Input Sanitization & XSS Prevention (5 tests)
|
|
|
|
**Purpose:** Prevent XSS, injection attacks, and malicious input processing.
|
|
|
|
#### Test: Sanitize HTML in action parameters
|
|
|
|
**Validates:**
|
|
- HTML tags stripped or escaped
|
|
- Script tags prevented from execution
|
|
- Safe rendering of user input
|
|
|
|
**Attack Vectors Tested:**
|
|
```javascript
|
|
// XSS attempts
|
|
'<script>alert("XSS")</script>'
|
|
'<img src=x onerror=alert("XSS")>'
|
|
'<svg onload=alert("XSS")>'
|
|
'<iframe src="javascript:alert(\'XSS\')"></iframe>'
|
|
```
|
|
|
|
**Expected Output:**
|
|
```html
|
|
<!-- Input: <script>alert("XSS")</script> -->
|
|
<!-- Output: <script>alert("XSS")</script> -->
|
|
<!-- Displayed as text, not executed -->
|
|
```
|
|
|
|
#### Test: Escape HTML entities
|
|
|
|
**Validates:**
|
|
- Special characters properly escaped
|
|
- No raw HTML injection
|
|
- Content-Type headers correct
|
|
|
|
**Entity Escaping:**
|
|
```
|
|
< → <
|
|
> → >
|
|
& → &
|
|
" → "
|
|
' → '
|
|
```
|
|
|
|
#### Test: Prevent JavaScript injection
|
|
|
|
**Validates:**
|
|
- `javascript:` protocol blocked in URLs
|
|
- Event handlers stripped
|
|
- No inline script execution
|
|
|
|
**Blocked Patterns:**
|
|
```javascript
|
|
javascript:alert('XSS')
|
|
data:text/html,<script>alert('XSS')</script>
|
|
vbscript:msgbox("XSS")
|
|
```
|
|
|
|
#### Test: Validate file paths
|
|
|
|
**Validates:**
|
|
- Path traversal attacks prevented
|
|
- Only allowed directories accessible
|
|
- Absolute paths rejected
|
|
|
|
**Attack Attempts:**
|
|
```
|
|
../../../etc/passwd
|
|
..\..\windows\system32\config\sam
|
|
/etc/passwd
|
|
C:\Windows\System32\config\SAM
|
|
```
|
|
|
|
**Expected:** All rejected with "Invalid path" error
|
|
|
|
#### Test: Prevent SQL injection
|
|
|
|
**Validates:**
|
|
- Parameterized queries used
|
|
- SQL keywords escaped
|
|
- No raw query concatenation
|
|
|
|
**Attack Vectors:**
|
|
```sql
|
|
'; DROP TABLE users; --
|
|
' OR '1'='1
|
|
admin'--
|
|
' UNION SELECT * FROM users--
|
|
```
|
|
|
|
**Expected:** Treated as literal search strings, no SQL execution
|
|
|
|
### 5. Authorization (3 tests)
|
|
|
|
**Purpose:** Enforce access control and permission checks.
|
|
|
|
#### Test: Reject unauthorized action calls
|
|
|
|
**Validates:**
|
|
- Actions requiring authentication are protected
|
|
- Anonymous users blocked
|
|
- Clear error message
|
|
|
|
**Protected Action:**
|
|
```php
|
|
#[Action]
|
|
#[RequiresAuth]
|
|
public function deleteAllData(): array
|
|
{
|
|
// Only authenticated users
|
|
}
|
|
```
|
|
|
|
**Expected Response:**
|
|
```
|
|
Status: 401 Unauthorized
|
|
Error: "Authentication required"
|
|
```
|
|
|
|
#### Test: Allow authorized action calls
|
|
|
|
**Validates:**
|
|
- Authenticated users can access protected actions
|
|
- Valid session/token accepted
|
|
- Actions execute successfully
|
|
|
|
**Flow:**
|
|
```
|
|
1. User logs in → Session created
|
|
2. Call protected action → Success
|
|
3. Action executes → Result returned
|
|
```
|
|
|
|
#### Test: Role-based authorization
|
|
|
|
**Validates:**
|
|
- Different roles have different permissions
|
|
- Role checks enforced
|
|
- Insufficient permissions rejected
|
|
|
|
**Role Matrix:**
|
|
```
|
|
Action: deleteAllData
|
|
- admin: ✅ Allowed
|
|
- moderator: ❌ Forbidden
|
|
- user: ❌ Forbidden
|
|
|
|
Action: editOwnProfile
|
|
- admin: ✅ Allowed
|
|
- moderator: ✅ Allowed
|
|
- user: ✅ Allowed
|
|
```
|
|
|
|
### 6. Session Security (3 tests)
|
|
|
|
**Purpose:** Secure session management and hijacking prevention.
|
|
|
|
#### Test: Invalidate session after logout
|
|
|
|
**Validates:**
|
|
- Session properly destroyed on logout
|
|
- Session cookie removed
|
|
- Subsequent requests rejected
|
|
|
|
**Flow:**
|
|
```
|
|
1. Login → Session active
|
|
2. Call protected action → Success
|
|
3. Logout → Session destroyed
|
|
4. Call protected action → 401 Unauthorized
|
|
```
|
|
|
|
#### Test: Detect session hijacking
|
|
|
|
**Validates:**
|
|
- Session binding to IP/User-Agent
|
|
- Suspicious activity detected
|
|
- Stolen sessions rejected
|
|
|
|
**Detection Criteria:**
|
|
- IP address change
|
|
- User-Agent change
|
|
- Geo-location anomaly
|
|
- Concurrent sessions from different locations
|
|
|
|
**Response:**
|
|
```
|
|
Status: 403 Forbidden
|
|
Error: "Session invalid - security violation detected"
|
|
Action: Session terminated, user notified
|
|
```
|
|
|
|
#### Test: Enforce session timeout
|
|
|
|
**Validates:**
|
|
- Sessions expire after inactivity
|
|
- Timeout configurable (default: 30 minutes)
|
|
- Expired sessions rejected
|
|
|
|
**Timeline:**
|
|
```
|
|
00:00 - Login
|
|
00:15 - Action call (session refreshed)
|
|
00:45 - No activity for 30 minutes
|
|
00:46 - Action call → 401 Session Expired
|
|
```
|
|
|
|
### 7. Content Security Policy (2 tests)
|
|
|
|
**Purpose:** Enforce CSP headers to prevent injection attacks.
|
|
|
|
#### Test: CSP headers present
|
|
|
|
**Validates:**
|
|
- `Content-Security-Policy` header set
|
|
- Proper directives configured
|
|
- No unsafe configurations
|
|
|
|
**Expected Header:**
|
|
```http
|
|
Content-Security-Policy:
|
|
default-src 'self';
|
|
script-src 'self' 'nonce-xyz123';
|
|
style-src 'self' 'unsafe-inline';
|
|
img-src 'self' data: https:;
|
|
connect-src 'self' wss://localhost;
|
|
font-src 'self' https://fonts.gstatic.com;
|
|
```
|
|
|
|
#### Test: Block inline scripts via CSP
|
|
|
|
**Validates:**
|
|
- Inline scripts blocked by CSP
|
|
- Console errors for violations
|
|
- CSP reports generated
|
|
|
|
**Violation Detection:**
|
|
```javascript
|
|
// Attempt to inject inline script
|
|
const script = document.createElement('script');
|
|
script.textContent = 'alert("XSS")';
|
|
document.body.appendChild(script);
|
|
|
|
// Expected Console Error:
|
|
// "Refused to execute inline script because it violates
|
|
// Content Security Policy directive: 'script-src self'"
|
|
```
|
|
|
|
## Test Page Requirements
|
|
|
|
Tests assume the following test page at `https://localhost/livecomponents/test/security`:
|
|
|
|
### Required HTML Elements
|
|
|
|
```html
|
|
<div data-component-id="counter:test">
|
|
<div id="counter-value">0</div>
|
|
<button id="trigger-action">Trigger Action</button>
|
|
<div class="action-success" style="display:none">Success</div>
|
|
<div class="error-message" style="display:none"></div>
|
|
<div class="rate-limit-error" style="display:none" data-retry-after=""></div>
|
|
</div>
|
|
|
|
<div data-component-id="text:test">
|
|
<div id="text-display"></div>
|
|
</div>
|
|
|
|
<div data-component-id="admin:test">
|
|
<div class="authorization-error" style="display:none"></div>
|
|
</div>
|
|
|
|
<!-- Login Form -->
|
|
<form id="login-form">
|
|
<input type="text" id="username" name="username" />
|
|
<input type="password" id="password" name="password" />
|
|
<button type="submit" id="login-btn">Login</button>
|
|
</form>
|
|
|
|
<div class="logged-in-indicator" style="display:none"></div>
|
|
<button id="logout-btn" style="display:none">Logout</button>
|
|
|
|
<!-- CSRF Token -->
|
|
<meta name="csrf-token" content="generated-token-value">
|
|
```
|
|
|
|
### Required Component Actions
|
|
|
|
```php
|
|
final readonly class SecurityTestComponent extends LiveComponent
|
|
{
|
|
#[Action]
|
|
#[RateLimit(requests: 10, window: 60)]
|
|
public function triggerAction(): array
|
|
{
|
|
return ['success' => true];
|
|
}
|
|
|
|
#[Action]
|
|
public function increment(string $idempotencyKey = null): array
|
|
{
|
|
// Idempotent increment
|
|
if ($idempotencyKey && $this->hasExecuted($idempotencyKey)) {
|
|
return $this->getCachedResult($idempotencyKey);
|
|
}
|
|
|
|
$newValue = $this->state->get('counter') + 1;
|
|
$this->state->set('counter', $newValue);
|
|
|
|
$result = ['value' => $newValue];
|
|
|
|
if ($idempotencyKey) {
|
|
$this->cacheResult($idempotencyKey, $result);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
#[Action]
|
|
public function setText(string $text): array
|
|
{
|
|
// Sanitize HTML
|
|
$sanitizedText = htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
|
|
$this->state->set('text', $sanitizedText);
|
|
|
|
return ['text' => $sanitizedText];
|
|
}
|
|
|
|
#[Action]
|
|
#[RequiresAuth]
|
|
#[RequiresRole('admin')]
|
|
public function performAdminAction(): array
|
|
{
|
|
return ['success' => true];
|
|
}
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
```env
|
|
# CSRF Protection
|
|
CSRF_TOKEN_TTL=7200 # 2 hours
|
|
CSRF_ROTATE_ON_ACTION=false # Rotate token after each action
|
|
|
|
# Rate Limiting
|
|
RATE_LIMIT_ENABLED=true
|
|
RATE_LIMIT_DEFAULT=60 # Requests per window
|
|
RATE_LIMIT_WINDOW=60 # Window in seconds
|
|
RATE_LIMIT_STORAGE=redis # Storage backend
|
|
|
|
# Idempotency
|
|
IDEMPOTENCY_ENABLED=true
|
|
IDEMPOTENCY_TTL=86400 # 24 hours
|
|
IDEMPOTENCY_STORAGE=redis
|
|
|
|
# Session Security
|
|
SESSION_LIFETIME=1800 # 30 minutes
|
|
SESSION_SECURE=true # HTTPS only
|
|
SESSION_HTTP_ONLY=true # No JavaScript access
|
|
SESSION_SAME_SITE=strict # SameSite cookie attribute
|
|
SESSION_BIND_IP=true # Bind to IP address
|
|
SESSION_BIND_USER_AGENT=true # Bind to User-Agent
|
|
|
|
# Content Security Policy
|
|
CSP_ENABLED=true
|
|
CSP_REPORT_ONLY=false # Enforce CSP (not just report)
|
|
CSP_REPORT_URI=/csp-report # CSP violation reporting endpoint
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### CSRF Tests Failing
|
|
|
|
**Symptoms:**
|
|
- CSRF token not found in requests
|
|
- All CSRF tests failing
|
|
|
|
**Solutions:**
|
|
|
|
1. **Verify CSRF middleware enabled:**
|
|
```php
|
|
// In middleware stack
|
|
new CsrfMiddleware($csrfTokenGenerator)
|
|
```
|
|
|
|
2. **Check meta tag presence:**
|
|
```html
|
|
<meta name="csrf-token" content="...">
|
|
```
|
|
|
|
3. **Verify JavaScript includes token:**
|
|
```javascript
|
|
const token = document.querySelector('meta[name="csrf-token"]').content;
|
|
// Include in requests
|
|
```
|
|
|
|
### Rate Limiting Not Working
|
|
|
|
**Symptoms:**
|
|
- All rapid requests succeed
|
|
- No 429 responses
|
|
|
|
**Solutions:**
|
|
|
|
1. **Check rate limit configuration:**
|
|
```bash
|
|
# Verify environment variables
|
|
docker exec php php -r "echo getenv('RATE_LIMIT_ENABLED');"
|
|
```
|
|
|
|
2. **Verify rate limiter initialized:**
|
|
```php
|
|
// Check DI container
|
|
$rateLimiter = $container->get(RateLimiter::class);
|
|
```
|
|
|
|
3. **Check storage backend:**
|
|
```bash
|
|
# For Redis backend
|
|
docker exec redis redis-cli KEYS "rate_limit:*"
|
|
```
|
|
|
|
### Idempotency Issues
|
|
|
|
**Symptoms:**
|
|
- Duplicate requests execute
|
|
- Idempotency keys not working
|
|
|
|
**Solutions:**
|
|
|
|
1. **Check idempotency key format:**
|
|
```javascript
|
|
// Must be unique per operation
|
|
idempotencyKey: `${userId}-${operationId}-${timestamp}`
|
|
```
|
|
|
|
2. **Verify storage:**
|
|
```bash
|
|
# For Redis
|
|
docker exec redis redis-cli KEYS "idempotency:*"
|
|
```
|
|
|
|
3. **Check TTL:**
|
|
```bash
|
|
# Verify keys not expiring too quickly
|
|
docker exec redis redis-cli TTL "idempotency:key-123"
|
|
```
|
|
|
|
### Authorization Failures
|
|
|
|
**Symptoms:**
|
|
- Authorized users rejected
|
|
- Role checks failing
|
|
|
|
**Solutions:**
|
|
|
|
1. **Verify session active:**
|
|
```javascript
|
|
const sessionActive = await page.evaluate(() => {
|
|
return window.__sessionActive === true;
|
|
});
|
|
```
|
|
|
|
2. **Check role assignment:**
|
|
```php
|
|
// Verify user roles
|
|
$user->hasRole('admin'); // Should return true
|
|
```
|
|
|
|
3. **Review authorization middleware:**
|
|
```php
|
|
// Ensure middleware in correct order
|
|
[AuthMiddleware, RoleMiddleware, ...]
|
|
```
|
|
|
|
## CI/CD Integration
|
|
|
|
### GitHub Actions
|
|
|
|
```yaml
|
|
name: Security Tests
|
|
|
|
on:
|
|
push:
|
|
branches: [main, develop]
|
|
pull_request:
|
|
branches: [main]
|
|
schedule:
|
|
- cron: '0 0 * * *' # Daily
|
|
|
|
jobs:
|
|
security-tests:
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
|
|
- uses: actions/setup-node@v3
|
|
with:
|
|
node-version: '18'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Install Playwright
|
|
run: npx playwright install --with-deps chromium
|
|
|
|
- name: Start dev server
|
|
run: make up
|
|
|
|
- name: Run security tests
|
|
run: npm run test:security
|
|
|
|
- name: Upload test results
|
|
if: always()
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: security-test-results
|
|
path: test-results/
|
|
|
|
- name: Security alert on failure
|
|
if: failure()
|
|
uses: actions/github-script@v6
|
|
with:
|
|
script: |
|
|
github.rest.issues.create({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
title: '🚨 Security Tests Failed',
|
|
labels: ['security', 'urgent'],
|
|
body: 'Security tests failed. Immediate review required.'
|
|
});
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
### 1. Regular Security Testing
|
|
|
|
- Run security tests before every deployment
|
|
- Include in CI/CD pipeline
|
|
- Monitor for new vulnerabilities
|
|
- Update tests for new attack vectors
|
|
|
|
### 2. Defense in Depth
|
|
|
|
- Multiple security layers (CSRF + Rate Limit + Auth)
|
|
- Fail securely (block by default, allow explicitly)
|
|
- Log all security events
|
|
- Alert on suspicious patterns
|
|
|
|
### 3. Security Monitoring
|
|
|
|
- Track failed authentication attempts
|
|
- Monitor rate limit violations
|
|
- Alert on XSS attempts
|
|
- Log authorization failures
|
|
|
|
### 4. Incident Response
|
|
|
|
- Defined escalation procedures
|
|
- Security event playbooks
|
|
- Regular security drills
|
|
- Post-incident analysis
|
|
|
|
## Resources
|
|
|
|
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
|
|
- [OWASP CSRF Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html)
|
|
- [OWASP XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)
|
|
- [Content Security Policy Reference](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)
|
|
- [Rate Limiting Best Practices](https://cloud.google.com/architecture/rate-limiting-strategies-techniques)
|
|
|
|
## Support
|
|
|
|
For security issues or questions:
|
|
1. Review this documentation
|
|
2. Check framework security documentation
|
|
3. Consult OWASP guidelines
|
|
4. **Report security vulnerabilities privately** to security@example.com
|
|
5. Create GitHub issue for non-security test failures
|