12 KiB
12 KiB
name, description, triggers
| name | description | triggers | ||||
|---|---|---|---|---|---|---|
| cors-configuration-validator | Automatically validates Cloudflare Workers CORS configuration, ensuring proper headers, OPTIONS handling, and origin validation for cross-origin requests |
|
CORS Configuration Validator SKILL
Activation Patterns
This SKILL automatically activates when:
new Response()objects are created- CORS-related headers are set or modified
- API endpoints that serve cross-origin requests
- OPTIONS method handling is detected
- Cross-origin request patterns are identified
Expertise Provided
Workers-Specific CORS Validation
- Header Validation: Ensures all required CORS headers are present
- OPTIONS Handling: Validates preflight request handling
- Origin Validation: Checks for proper origin validation logic
- Method Validation: Ensures correct allowed methods
- Header Validation: Validates allowed headers configuration
- Security: Prevents overly permissive CORS configurations
Specific Checks Performed
❌ CORS Anti-Patterns
// These patterns trigger immediate alerts:
// Missing CORS headers
export default {
async fetch(request: Request, env: Env) {
return new Response(JSON.stringify(data));
// Browsers will block cross-origin requests!
}
}
// Overly permissive for authenticated APIs
const corsHeaders = {
'Access-Control-Allow-Origin': '*', // ANY origin can call!
'Access-Control-Allow-Credentials': 'true' // With credentials!
};
✅ CORS Best Practices
// These patterns are validated as correct:
// Proper CORS with origin validation
function getCorsHeaders(origin: string) {
const allowedOrigins = ['https://app.example.com', 'https://example.com'];
const allowOrigin = allowedOrigins.includes(origin) ? origin : allowedOrigins[0];
return {
'Access-Control-Allow-Origin': allowOrigin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
};
}
export default {
async fetch(request: Request, env: Env) {
const origin = request.headers.get('Origin') || '';
if (request.method === 'OPTIONS') {
return new Response(null, { headers: getCorsHeaders(origin) });
}
const response = new Response(JSON.stringify(data));
Object.entries(getCorsHeaders(origin)).forEach(([k, v]) => {
response.headers.set(k, v);
});
return response;
}
}
Integration Points
Complementary to Existing Components
- cloudflare-security-checker SKILL: Handles overall security, SKILL focuses specifically on CORS
- workers-runtime-validator SKILL: Ensures runtime compatibility, SKILL validates CORS patterns
- edge-performance-oracle SKILL: Handles performance, SKILL ensures CORS doesn't impact performance
Escalation Triggers
- Complex CORS architecture questions →
cloudflare-security-sentinelagent - Advanced authentication with CORS →
cloudflare-security-sentinelagent - CORS troubleshooting →
cloudflare-security-sentinelagent
Validation Rules
P1 - Critical (Will Break Cross-Origin Requests)
- Missing CORS Headers: No CORS headers on API responses
- Missing OPTIONS Handler: No preflight request handling
- Invalid Header Combinations: Conflicting CORS header combinations
P2 - High (Security Risk)
- Overly Permissive Origin:
Access-Control-Allow-Origin: *with credentials - Wildcard Methods:
Access-Control-Allow-Methods: *with sensitive operations - Missing Origin Validation: Accepting any origin without validation
P3 - Medium (Best Practices)
- Missing Cache Headers: No
Access-Control-Max-Agefor preflight caching - Incomplete Headers: Missing some optional but recommended headers
- Hardcoded Origins: Origins not easily configurable
Remediation Examples
Fixing Missing CORS Headers
// ❌ Critical: No CORS headers (browsers block requests)
export default {
async fetch(request: Request, env: Env) {
const data = { message: 'Hello from API' };
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json' }
// Missing CORS headers!
});
}
}
// ✅ Correct: Complete CORS implementation
function getCorsHeaders(origin: string) {
const allowedOrigins = ['https://app.example.com', 'https://example.com'];
const allowOrigin = allowedOrigins.includes(origin) ? origin : allowedOrigins[0];
return {
'Access-Control-Allow-Origin': allowOrigin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
};
}
export default {
async fetch(request: Request, env: Env) {
const origin = request.headers.get('Origin') || '';
// Handle preflight requests
if (request.method === 'OPTIONS') {
return new Response(null, { headers: getCorsHeaders(origin) });
}
const data = { message: 'Hello from API' };
return new Response(JSON.stringify(data), {
headers: {
'Content-Type': 'application/json',
...getCorsHeaders(origin)
}
});
}
}
Fixing Overly Permissive CORS
// ❌ High: Overly permissive for authenticated API
export default {
async fetch(request: Request, env: Env) {
const corsHeaders = {
'Access-Control-Allow-Origin': '*', // ANY origin!
'Access-Control-Allow-Credentials': 'true', // With credentials!
'Access-Control-Allow-Methods': '*', // ANY method!
};
// This allows any website to make authenticated requests!
return new Response('Sensitive data', { headers: corsHeaders });
}
}
// ✅ Correct: Secure CORS for authenticated API
function getSecureCorsHeaders(origin: string) {
const allowedOrigins = [
'https://app.example.com',
'https://admin.example.com',
'https://example.com'
];
// Only allow known origins
const allowOrigin = allowedOrigins.includes(origin) ? origin : allowedOrigins[0];
return {
'Access-Control-Allow-Origin': allowOrigin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE', // Specific methods
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Max-Age': '86400',
};
}
export default {
async fetch(request: Request, env: Env) {
const origin = request.headers.get('Origin') || '';
// Verify authentication
const authHeader = request.headers.get('Authorization');
if (!authHeader || !isValidAuth(authHeader)) {
return new Response('Unauthorized', { status: 401 });
}
return new Response('Sensitive data', {
headers: getSecureCorsHeaders(origin)
});
}
}
Fixing Missing OPTIONS Handler
// ❌ Critical: No OPTIONS handling (preflight fails)
export default {
async fetch(request: Request, env: Env) {
if (request.method === 'POST') {
// Handle POST request
return new Response('POST handled');
}
return new Response('Method not allowed', { status: 405 });
}
}
// ✅ Correct: Proper OPTIONS handling
export default {
async fetch(request: Request, env: Env) {
const origin = request.headers.get('Origin') || '';
// Handle preflight requests
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': origin,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
}
});
}
if (request.method === 'POST') {
return new Response('POST handled', {
headers: {
'Access-Control-Allow-Origin': origin,
}
});
}
return new Response('Method not allowed', { status: 405 });
}
}
Fixing Dynamic CORS for Different Environments
// ❌ Medium: Hardcoded origins (not flexible)
function getCorsHeaders() {
return {
'Access-Control-Allow-Origin': 'https://app.example.com', // Hardcoded
'Access-Control-Allow-Methods': 'GET, POST',
};
}
// ✅ Correct: Configurable and secure CORS
function getCorsHeaders(origin: string, env: Env) {
// Get allowed origins from environment
const allowedOrigins = (env.ALLOWED_ORIGINS || 'https://app.example.com')
.split(',')
.map(o => o.trim());
const allowOrigin = allowedOrigins.includes(origin) ? origin : allowedOrigins[0];
return {
'Access-Control-Allow-Origin': allowOrigin,
'Access-Control-Allow-Methods': env.ALLOWED_METHODS || 'GET, POST, PUT, DELETE',
'Access-Control-Allow-Headers': env.ALLOWED_HEADERS || 'Content-Type, Authorization',
'Access-Control-Max-Age': '86400',
};
}
export default {
async fetch(request: Request, env: Env) {
const origin = request.headers.get('Origin') || '';
if (request.method === 'OPTIONS') {
return new Response(null, { headers: getCorsHeaders(origin, env) });
}
return new Response('Response', {
headers: getCorsHeaders(origin, env)
});
}
}
CORS Header Reference
Essential Headers
{
'Access-Control-Allow-Origin': 'https://example.com', // Required
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', // Required for preflight
'Access-Control-Allow-Headers': 'Content-Type, Authorization', // Required for preflight
}
Optional but Recommended Headers
{
'Access-Control-Max-Age': '86400', // Cache preflight for 24 hours
'Access-Control-Allow-Credentials': 'true', // For cookies/auth
'Vary': 'Origin', // Important for caching with multiple origins
}
Security Considerations
// ❌ Don't do this for authenticated APIs:
{
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true'
}
// ✅ Do this instead:
{
'Access-Control-Allow-Origin': 'https://app.example.com', // Specific origin
'Access-Control-Allow-Credentials': 'true'
}
MCP Server Integration
When Cloudflare MCP server is available:
- Query latest CORS best practices and security recommendations
- Get current browser CORS specification updates
- Check for common CORS vulnerabilities and mitigations
Benefits
Immediate Impact
- Prevents CORS Errors: Catches missing headers before deployment
- Improves Security: Prevents overly permissive CORS configurations
- Better User Experience: Ensures cross-origin requests work properly
Long-term Value
- Consistent CORS Standards: Ensures all APIs follow proper CORS patterns
- Reduced Debugging Time: Immediate feedback on CORS issues
- Security Compliance: Prevents CORS-related security vulnerabilities
Usage Examples
During Response Creation
// Developer types: new Response(data)
// SKILL immediately activates: "⚠️ HIGH: Response missing CORS headers. Cross-origin requests will be blocked by browsers."
During API Development
// Developer types: 'Access-Control-Allow-Origin': '*'
// SKILL immediately activates: "⚠️ HIGH: Overly permissive CORS with wildcard origin. Consider specific origins for security."
During Method Handling
// Developer types: if (request.method === 'POST') { ... }
// SKILL immediately activates: "⚠️ HIGH: Missing OPTIONS handler for preflight requests. Add OPTIONS method handling."
CORS Checklist
Required for Cross-Origin Requests
Access-Control-Allow-Originheader set- OPTIONS method handled for preflight requests
Access-Control-Allow-Methodsheader for preflightAccess-Control-Allow-Headersheader for preflight
Security Best Practices
- Origin validation (not wildcard for authenticated APIs)
- Specific allowed methods (not wildcard)
- Proper credentials handling
- Environment-based origin configuration
Performance Optimization
Access-Control-Max-Ageheader setVary: Originheader for caching- Efficient preflight handling
This SKILL ensures CORS is configured correctly by providing immediate, autonomous validation of CORS patterns, preventing common cross-origin issues and security vulnerabilities.