# 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
{
"error": "Rate limit exceeded",
"retryAfter": 60,
"limit": 10,
"window": 60
}
```
#### 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
''
'
'
'