CORS Testing — How to Verify Cross-Origin Configuration with Curl, Postman, and Browsers
In this tutorial, you will learn about CORS Testing. We cover key concepts, practical examples, and best practices to help you master this topic.
CORS testing requires validating headers at multiple levels: with curl for server-side configuration, with Postman for manual interactive testing, and in the browser for true client-side behavior verification.
What You'll Learn
- Testing CORS with curl commands
- Using Postman for CORS validation
- Automating CORS tests in CI/CD
Why It Matters
CORS misconfigurations can silently block production traffic or expose security vulnerabilities. Automated CORS testing in CI/CD prevents deployment of broken configurations. DodaTech's CI pipeline runs CORS tests against every API deployment.
flowchart LR
A["CORS Testing Strategy"] --> B["curl: Basic header check"]
A --> C["Postman: Manual testing"]
A --> D["Browser: Real behavior"]
A --> E["Automated: CI/CD tests"]
B --> F["Verify ACAO, ACAC presence"]
C --> G["Test multiple origins"]
D --> H["Verify preflight + actual"]
E --> I["Regression tests per deploy"]
Code Examples
# Complete curl CORS test suite
# 1. Test simple GET request
echo "=== Test 1: Simple GET ==="
curl -s -I -H "Origin: https://app.example.com" \
https://api.example.com/data | grep -i "access-control"
# 2. Test preflight
echo "=== Test 2: Preflight OPTIONS ==="
curl -s -X OPTIONS -I \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: POST" \
-H "Access-Control-Request-Headers: Content-Type" \
https://api.example.com/data | grep -i "access-control"
# 3. Test blocked origin
echo "=== Test 3: Blocked Origin ==="
curl -s -I -H "Origin: https://evil.com" \
https://api.example.com/data | grep -i "access-control"
# 4. Test with credentials
echo "=== Test 4: With Credentials ==="
curl -s -I -H "Origin: https://app.example.com" \
-H "Cookie: session=abc" \
https://api.example.com/profile | grep -i "access-control"
// Automated CORS test with Node.js
const http = require('http');
function testCors(origin, url, method = 'GET') {
return new Promise((resolve, reject) => {
const options = {
headers: { 'Origin': origin },
method: method === 'OPTIONS' ? 'OPTIONS' : method
};
const req = http.request(url, options, (res) => {
const headers = res.headers;
const result = {
origin,
url,
method: options.method,
'access-control-allow-origin': headers['access-control-allow-origin'],
'access-control-allow-methods': headers['access-control-allow-methods'],
'access-control-allow-credentials': headers['access-control-allow-credentials'],
status: res.statusCode
};
resolve(result);
});
req.end();
});
}
// Test multiple scenarios
async function runCorsTests() {
const tests = [
{ origin: 'https://app.example.com', url: 'http://localhost:3000/api/data' },
{ origin: 'https://evil.com', url: 'http://localhost:3000/api/data' },
{ origin: 'https://app.example.com', url: 'http://localhost:3000/api/data', method: 'OPTIONS' }
];
for (const test of tests) {
const result = await testCors(test.origin, test.url, test.method);
console.log(result);
}
}
# Automated CORS tests with pytest
import requests
class TestCORS:
BASE_URL = "https://api.example.com"
ALLOWED_ORIGIN = "https://app.example.com"
BLOCKED_ORIGIN = "https://evil.com"
def test_allowed_origin_has_acao(self):
response = requests.get(
f"{self.BASE_URL}/data",
headers={"Origin": self.ALLOWED_ORIGIN}
)
assert response.headers.get("Access-Control-Allow-Origin") == "*"
def test_preflight_allows_post(self):
response = requests.options(
f"{self.BASE_URL}/data",
headers={
"Origin": self.ALLOWED_ORIGIN,
"Access-Control-Request-Method": "POST"
}
)
methods = response.headers.get("Access-Control-Allow-Methods", "")
assert "POST" in methods
def test_blocked_origin_should_have_no_acao(self):
"""For dynamic origin APIs, blocked origins should have no ACAO"""
response = requests.get(
f"{self.BASE_URL}/secure-data",
headers={"Origin": self.BLOCKED_ORIGIN}
)
acao = response.headers.get("Access-Control-Allow-Origin")
assert acao is None or acao != self.BLOCKED_ORIGIN
Common Mistakes
1. Testing Only with Curl
Curl does not enforce CORS. Always verify in a real browser.
2. Not Testing Blocked Origins
Positive tests are not enough. Verify that unauthorized origins are actually blocked.
3. Ignoring Preflight Testing
Preflight requests may have different behavior than actual requests. Test both.
4. Not Testing with Credentials
CORS behavior with credentials differs significantly. Test both credentialed and anonymous requests.
5. Testing Only Against Production
Test CORS in staging with the same configuration as production to catch issues before deployment.
Practice Questions
- What curl flag shows response headers?
- How do you simulate a preflight request with curl?
- What is the difference between testing CORS with curl vs a browser?
- How do you automate CORS tests in CI/CD?
- What should you test beyond the happy path?
Answers:
- -I (or --head) shows response headers only.
- Use -X OPTIONS with Access-Control-Request-Method and Access-Control-Request-Headers headers.
- Curl shows what the server sends; the browser actually enforces CORS rules.
- Use pytest or Jest to send requests with custom Origin headers and assert CORS response headers.
- Test blocked origins, missing headers, credential conflicts, and preflight failures.
Challenge: Build a comprehensive CORS testing framework that runs in CI/CD. Include tests for allowed origins, blocked origins, preflight requests, credentialed requests, wildcard configurations, and header exposure. Generate a CORS Compliance report.
FAQ
Mini Project
Build a CORS testing service: provide a URL and an origin, and the service sends all relevant CORS test scenarios (simple, preflight, credentialed, blocked origin) and returns a detailed compliance report with pass/fail status for each CORS header requirement. Include configuration fix suggestions.
What's Next
Study CORS security misconfiguration patterns to avoid common vulnerabilities, then explore CORS vulnerabilities including advanced attack vectors.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro