check-cors-security
CORS Security Audit (A05:2021)
Analyze PHP code for CORS misconfiguration vulnerabilities.
Detection Patterns
1. Wildcard Origin
// CRITICAL: Allows any website to make requests
header('Access-Control-Allow-Origin: *');
// In framework config:
'allowed_origins' => ['*'], // Any origin!
2. Credentials with Wildcard
// CRITICAL: Browser ignores this (spec violation), but shows misconfiguration intent
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
// Cannot use * with credentials — forces dynamic origin reflection
3. Dynamic Origin Reflection (Dangerous)
// CRITICAL: Reflects any Origin header — equivalent to wildcard with credentials
class CorsMiddleware
{
public function handle(Request $request, Response $response): Response
{
$origin = $request->headers->get('Origin');
$response->headers->set('Access-Control-Allow-Origin', $origin); // Reflects ANY origin!
$response->headers->set('Access-Control-Allow-Credentials', 'true');
return $response;
}
}
// CORRECT: Whitelist of allowed origins
class CorsMiddleware
{
private const array ALLOWED_ORIGINS = [
'https://app.example.com',
'https://admin.example.com',
];
public function handle(Request $request, Response $response): Response
{
$origin = $request->headers->get('Origin');
if (in_array($origin, self::ALLOWED_ORIGINS, true)) {
$response->headers->set('Access-Control-Allow-Origin', $origin);
$response->headers->set('Access-Control-Allow-Credentials', 'true');
$response->headers->set('Vary', 'Origin');
}
return $response;
}
}
4. Missing Vary: Origin Header
// VULNERABLE: Without Vary, CDN/proxy may cache wrong CORS headers
$response->headers->set('Access-Control-Allow-Origin', $dynamicOrigin);
// Missing: $response->headers->set('Vary', 'Origin');
// CDN caches response for origin A, serves to origin B
5. Overly Permissive Methods/Headers
// VULNERABLE: Allows all methods including DELETE, PATCH
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');
// CORRECT: Minimal required methods
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
$response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
6. Missing Preflight Handling
// VULNERABLE: OPTIONS request not handled — browser blocks request
class ApiController
{
public function handle(Request $request): Response
{
// No OPTIONS handling — preflight fails
return $this->processRequest($request);
}
}
// CORRECT: Handle preflight
if ($request->getMethod() === 'OPTIONS') {
$response = new Response('', 204);
$response->headers->set('Access-Control-Allow-Origin', $allowedOrigin);
$response->headers->set('Access-Control-Allow-Methods', 'GET, POST');
$response->headers->set('Access-Control-Max-Age', '86400');
return $response;
}
7. Regex Origin Matching (Bypass Risk)
// VULNERABLE: Regex can be bypassed
$origin = $request->headers->get('Origin');
if (preg_match('/example\.com$/', $origin)) {
// Matches: evil-example.com, phishing-example.com
$response->headers->set('Access-Control-Allow-Origin', $origin);
}
// CORRECT: Exact match or proper regex
if (preg_match('/^https:\/\/([a-z]+\.)?example\.com$/', $origin)) {
$response->headers->set('Access-Control-Allow-Origin', $origin);
}
Grep Patterns
# CORS headers
Grep: "Access-Control-Allow-Origin|Access-Control-Allow-Credentials" --glob "**/*.php"
Grep: "Access-Control-Allow-Methods|Access-Control-Allow-Headers" --glob "**/*.php"
# Wildcard origin
Grep: "Allow-Origin.*\*|allowed_origins.*\*" --glob "**/*.php" --glob "**/*.yaml"
# Dynamic origin reflection
Grep: "Origin.*header|getHeader.*Origin" --glob "**/*.php"
# CORS framework config
Grep: "cors|CORS" --glob "**/*.yaml" --glob "**/*.yml" --glob "**/*.php"
# Missing Vary header
Grep: "Allow-Origin" --glob "**/*.php"
Grep: "Vary.*Origin" --glob "**/*.php"
# Preflight handling
Grep: "OPTIONS|preflight" --glob "**/*.php"
Severity Classification
| Pattern | Severity |
|---|---|
| Dynamic origin reflection + credentials | 🔴 Critical |
| Wildcard origin on authenticated API | 🔴 Critical |
| Weak regex origin matching | 🟠 Major |
| Missing Vary: Origin | 🟠 Major |
| Wildcard methods/headers | 🟡 Minor |
| Missing preflight handling | 🟡 Minor |
Output Format
### CORS Security: [Description]
**Severity:** 🔴/🟠/🟡
**Location:** `file.php:line`
**CWE:** CWE-942 (Overly Permissive CORS Policy)
**OWASP:** A05:2021 — Security Misconfiguration
**Issue:**
[Description of the CORS misconfiguration]
**Attack Scenario:**
[How attacker exploits this from malicious origin]
**Current Configuration:**
Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true
**Fix:**
```php
// Secure CORS configuration
More from dykyi-roman/awesome-claude-code
psr-overview-knowledge
PHP Standards Recommendations (PSR) overview knowledge base. Provides comprehensive reference for all accepted PSRs including PSR-1,3,4,6,7,11,12,13,14,15,16,17,18,20. Use for PSR selection decisions and compliance audits.
22detect-code-smells
Detects code smells in PHP codebases. Identifies God Class, Feature Envy, Data Clumps, Long Parameter List, Long Method, Primitive Obsession, Message Chains, Inappropriate Intimacy. Generates actionable reports with refactoring recommendations.
15clean-arch-knowledge
Clean Architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Clean Architecture and Hexagonal Architecture audits.
15ddd-knowledge
DDD architecture knowledge base. Provides patterns, antipatterns, and PHP-specific guidelines for Domain-Driven Design audits.
14testing-knowledge
Testing knowledge base for PHP 8.4 projects. Provides testing pyramid, AAA pattern, naming conventions, isolation principles, DDD testing guidelines, and PHPUnit patterns.
12bug-root-cause-finder
Root cause analysis methods for PHP bugs. Provides 5 Whys technique, fault tree analysis, git bisect guidance, and stack trace parsing.
12