Bug Bounty Course -- Day 31 of 60
52%

CORS Misconfiguration Bug Bounty 2026 — Find, Test & Report Cross-Origin Bugs | Bug Bounty Day 31 of 60

CORS Misconfiguration Bug Bounty 2026 — Find, Test & Report Cross-Origin Bugs | Bug Bounty Day 31 of 60
✨ AI Summary
💰 BUG BOUNTY HUNTER
FREE

Part of the Bug Bounty 60-Day Course

CORS misconfiguration – Day 31 of 60 · 51% complete

One thing I’ve noticed while testing web applications is that CORS misconfigurations are often overlooked. Not because they’re particularly difficult to find, but because many hunters don’t know what to look for when they encounter an unusual response header. Here’s the interesting part: you don’t need a complicated payload or an advanced exploit to get started. In Burp Suite, you can modify a single request header, send the request again and inspect the server’s response in seconds. That simple check can reveal whether an application is trusting an origin it shouldn’t. And when that mistake allows an attacker-controlled website to read sensitive information from an authenticated user’s session, the impact can be significant.

By the end of this guide, you’ll know how to test reflected origins, identify null origin and unsafe subdomain validation, verify whether credentialed access is actually exploitable, and build a reproducible proof of concept for a bug bounty report. More importantly, you’ll learn how to distinguish a harmless CORS configuration issue from a vulnerability with real security impact. Let’s start with the three-second check I use.

🎯 What you’ll master in Day 31

Understand exactly what CORS is and why the browser enforces it
Identify the three misconfiguration patterns — reflected origin, null origin, subdomain wildcard
Test all three patterns in Burp Repeater in under five minutes
Know exactly when Allow-Credentials: true makes a finding exploitable
Build a working JavaScript PoC and write a paid-quality report

⏱ ~28 min read · 3 hands-on exercises · Burp Suite + PortSwigger Academy

Before you start you’ll want: Burp Suite from Day 5 intercepting your browser, a free PortSwigger Web Security Academy account for the hands-on lab (they have CORS labs that are specifically built for this), and a clear head on the HTTP basics from Day 3 — CORS is entirely a header-level conversation between browser and server.

What CORS is and why the browser cares

Before we start hunting for CORS vulnerabilities, I want you to understand one thing: your browser is constantly protecting you from websites you don’t trust. Imagine you’re logged in to your bank in one browser tab. Now, in another tab, you visit a website created by an attacker. Could that website simply run JavaScript, access your bank account and read your private information? Fortunately, the browser has a security rule designed to prevent exactly that. It’s called the Same-Origin Policy (SOP).

Here’s how I explain it to beginners. JavaScript running on one website cannot freely read responses from another website unless the destination server explicitly allows it. The browser considers an origin to be a combination of three things: protocol, domain and port. For example, https://bank.com and https://api.bank.com are two different origins, even though they belong to the same organisation. This separation is important because without it, a malicious website could potentially make requests using your existing browser session and read sensitive information from other websites.

This is where CORS (Cross-Origin Resource Sharing) comes into the picture. Think of it as a permission system that allows a server to tell the browser which external websites are trusted to read its responses. The server communicates this permission through HTTP response headers. The three headers I always want you to recognise are Access-Control-Allow-Origin, which identifies the permitted origin; Access-Control-Allow-Credentials, which controls whether credentialed requests can be shared with an approved origin; and Access-Control-Allow-Methods, which specifies the permitted HTTP methods.

When everything is configured correctly, CORS allows legitimate applications to communicate across different origins without weakening browser security. But when a developer gets the origin validation wrong, things become interesting for us as bug bounty hunters. A server might accidentally trust an attacker-controlled website and allow its JavaScript to read sensitive responses from an authenticated user’s session. That’s the security boundary we’re looking for. And in the next sections, I’ll show you exactly how to identify these mistakes using Burp Suite.


How the misconfiguration happens

In my experience, the most interesting CORS bugs aren’t caused by developers forgetting what CORS does. They’re usually caused by small mistakes in the code that decides which origins should be trusted. Let me show you three situations I want you to look for when testing an application.

The first mistake is reflected origin validation. A developer wants their frontend at app.company.com to communicate with an API at api.company.com. Instead of maintaining an explicit allowlist of trusted origins, the application reads whatever arrives in the incoming Origin header and sends that same value back in Access-Control-Allow-Origin. If the server blindly reflects https://evil.com, we’ve potentially found something worth investigating. The important question is whether the browser will also allow credentials and whether the response contains sensitive information.

The second mistake is careless domain matching. I’ve seen developers try to solve the allowlist problem with simple string checks. For example, they check whether an origin contains or ends with company.com without properly validating the hostname boundary. An attacker-controlled domain such as evilcompany.com might then pass a poorly written check. Remember, a trusted domain name appearing somewhere inside an attacker-controlled hostname does not make that hostname trustworthy. Always test the complete origin, not just a matching piece of text.

The third mistake is leaving the null origin trusted. Developers sometimes add null to their CORS configuration during local testing or development and forget to remove it before deployment. Browsers can send a null origin in certain contexts, including sandboxed documents with an opaque origin. If a production API trusts that origin and also permits credentialed requests, it deserves a closer look.

Here’s what I want you to take away: don’t report a CORS vulnerability just because you see an unusual response header. Your job is to prove the security impact. Check whether an untrusted origin is accepted, whether credentialed cross-origin access is permitted, and whether an authenticated browser can actually read sensitive response data. That evidence is what turns an interesting observation into a meaningful bug bounty finding.

🧠 EXERCISE 1 — THINK LIKE A HACKER (10 MIN · NO TOOLS)

Spot the vulnerability in each server-side CORS validation snippet before you run anything:

  1. A server checks: if request.headers['Origin'].endswith('company.com'): allow. Why is this exploitable, and what origin would you craft to bypass it?
  2. A server returns Access-Control-Allow-Origin: * on all endpoints. Is this exploitable? Does your answer change if the same endpoint also returns Access-Control-Allow-Credentials: true?
  3. A login endpoint returns authenticated data and is configured with a null-origin whitelist for “browser compatibility.” Explain how an attacker can exploit this despite the null origin not being a real website.
Answer reveal: (1) The suffix check passes for any domain ending in company.com — including evilcompany.com, notcompany.com or company.com.evil.com. You’d craft Origin: https://evilcompany.com and the check passes. (2) A wildcard * alone is not exploitable for credentialed requests because the browser refuses to include cookies with a wildcard origin, and it prevents Allow-Credentials: true from being combined with * by spec. If the server tries to return both, the browser ignores the credentials. The wildcard is fine. It’s only when the server dynamically reflects a specific origin AND sets Allow-Credentials: true that it’s exploitable. (3) Sandboxed iframes have a null origin in the browser. An attacker hosts a page with <iframe sandbox="allow-scripts allow-forms" src="..."> inside which JavaScript sends credentialed requests to the target. The iframe’s null origin is whitelisted, so the server allows it with credentials. The attacker reads the response through the iframe’s document context.
📸 Post your answer to question 1 (what domain would you test?) in #day-31-cors.


The three CORS vulnerability patterns I always check

When I’m testing an application for CORS misconfigurations, I don’t approach every suspicious response in the same way. I look for three common patterns: reflected origin, null origin trust, and unsafe subdomain or suffix validation. Each one reveals a different mistake in how the server decides which websites it trusts. Understanding the difference matters because the testing approach, proof of concept and potential security impact can vary significantly.

I want you to remember something before we move into Burp Suite: spotting a suspicious Access-Control-Allow-Origin header is only the beginning. You still need to establish whether an untrusted origin can read an authenticated response and whether that response contains sensitive information. I’ll walk you through each pattern, show you exactly what to look for in the request and response, and explain how to judge the actual impact. By the end, you should be able to recognise these three patterns without confusing a simple configuration mistake with a reportable vulnerability.

CORS misconfiguration bug bounty 2026 showing three vulnerability patterns: reflected origin, null origin and subdomain suffix matching with credentialed CORS headers.
Three CORS misconfiguration patterns every bug bounty hunter should recognize — reflected origin, null origin and subdomain suffix matching.

Testing CORS in Burp Suite: The Three-Step Check

Now let’s get practical. When I’m testing a web application for CORS vulnerabilities, I don’t start by randomly changing headers across hundreds of requests. I first find an authenticated API endpoint that returns information belonging to the logged-in user. The easiest way to do this is to open your browser’s Developer Tools, switch to the Network tab, browse through authenticated sections of the application and look for API requests returning user-specific data. Once I find a suitable request, I send it to Burp Suite Repeater.

From there, I follow three simple checks. Each one tests a different type of origin validation mistake. You don’t need an elaborate payload at this stage. A carefully modified Origin header and a close look at the response headers will tell you whether the server is behaving suspiciously.

STEP 1 — TEST REFLECTED ORIGIN IN BURP REPEATER
# Find an authenticated API request in Burp
# Send the request to Repeater
# Add or replace the Origin header:
Origin: https://evil.com
# Send the request and inspect the response headers
# SUSPICIOUS response:
Access-Control-Allow-Origin: https://evil.com
Access-Control-Allow-Credentials: true
# The server has reflected an untrusted origin.
# Compare with these possible safe responses:
Access-Control-Allow-Origin: *
# Wildcard access cannot be used for credentialed browser requests.
Access-Control-Allow-Origin: https://app.legitimatecompany.com
# Safe only if this is an explicitly trusted origin.

Here’s what I want you to notice: if the server responds with the exact attacker-controlled origin and also returns Access-Control-Allow-Credentials: true, you’ve found a strong lead. But don’t stop here. Check whether the response contains sensitive authenticated information. Repeater lets you inspect the server’s behaviour, but it doesn’t enforce the browser’s Same-Origin Policy. We’ll need a browser-based proof of concept to confirm actual cross-origin access.

STEP 2 — TEST NULL ORIGIN
# In the same Repeater request, replace the Origin header:
Origin: null
# Send the request and inspect the response
# SUSPICIOUS response:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
# The server appears to trust the null origin.
# Further browser testing is required to confirm exploitability.

The second check is just as simple. I replace the previous origin with null and send the request again. If the server responds by allowing the null origin and credentials, I investigate further. Why? Because browsers can assign a null origin to certain contexts, including sandboxed iframes without the allow-same-origin permission. This can create an opportunity for an attacker-controlled page to read sensitive responses if the remaining browser and application conditions are satisfied.

STEP 3 — TEST SUBDOMAIN AND SUFFIX VALIDATION
# Assume the legitimate application domain is company.com
# Test these attacker-controlled origins individually:
Origin: https://evilcompany.com
Origin: https://company.com.evil.com
Origin: https://notacompany.com
# Check whether an untrusted origin is reflected
# A match may indicate weak substring or suffix validation
# Also investigate trusted subdomains:
Origin: https://sub.company.com
# If this origin is trusted and the subdomain has an XSS flaw,
# an attacker may be able to use that trusted origin to read
# sensitive cross-origin API responses.

For the third check, I want you to think about how the developer implemented domain validation. If the target is company.com, I test attacker-controlled domains that contain the trusted name or place it in a misleading position. For example, evilcompany.com and company.com.evil.com help identify different types of poorly implemented substring or suffix checks.

Don’t assume every reflected test origin proves the exact validation flaw. Inspect the server’s behaviour and determine which matching rule is responsible. I also check whether legitimate subdomains are trusted. If a trusted subdomain has an XSS vulnerability, that combination can sometimes provide a route to reading sensitive API responses across origins.

💡 My time-saving recon trick: Before manually changing Origin headers, I search Burp Suite’s HTTP history for responses containing Access-Control-Allow-Origin. This gives me a starting list of endpoints that already implement CORS. I prioritise authenticated API responses and investigate which origins are accepted. A Burp passive scan finding is a useful signal, not proof of exploitability. My final check is always whether an attacker-controlled browser origin can actually read sensitive authenticated response data.

One final thing: don’t forget that browser behaviour matters. Cookie SameSite settings, third-party cookie restrictions, the actual authentication mechanism and the browser’s CORS checks can all affect whether an attack works. A convincing bug bounty report should demonstrate the complete chain, not just two interesting response headers.

⚡ EXERCISE 2 — BURP LAB (20 MIN)

Test all three patterns on an authorised lab. Use PortSwigger Web Security Academy’s CORS labs (free account, no sign-up required for labs):

  1. Go to PortSwigger CORS Lab: Basic Origin Reflection. Proxy through Burp. Find the vulnerable API endpoint and test with Origin: https://evil.com. Screenshot the reflected origin in the response.
  2. Confirm Access-Control-Allow-Credentials: true is present. Note what authenticated data the endpoint returns (account balance, email address, etc.).
  3. Try the null origin on the same endpoint. Does it also reflect null? This tells you whether multiple patterns exist on the same endpoint.
  4. In your notes: what is the realistic worst-case for an attacker who exploits this? What can they read, and from whose session?
✅ What you just learned: you identified a CORS vulnerability using only Burp Repeater and one custom header. The lab gives you a realistic authenticated endpoint returning sensitive data — which is exactly what your report’s Impact section describes. You didn’t need any special tools or extensions for the identification step.
📸 Screenshot of the reflected origin response for #day-31-cors.


Building the JavaScript PoC — Prove the CORS Vulnerability

So far, we’ve used Burp Suite to identify suspicious CORS behaviour. But here’s the question I always ask before submitting a finding: can I demonstrate that a browser running on an untrusted origin can actually read sensitive information from an authenticated session? That’s where a JavaScript proof of concept (PoC) becomes important.

Think of it this way: a Burp Repeater screenshot shows how the server responds to a modified Origin header. A browser-based PoC takes the investigation one step further by testing whether the browser accepts the CORS response and allows JavaScript to read the returned data. For higher-impact findings, this is particularly valuable because it demonstrates the actual security consequence rather than just an unusual HTTP header.

Let’s build a simple PoC. I’ll use a placeholder API endpoint below. Replace it with an endpoint from your own authorised testing environment that returns data belonging to your test account.

CORS JAVASCRIPT PoC — BROWSER-BASED VERIFICATION
<!– Run only against an authorised test target –>
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>CORS Security Test</title>
</head>
<body>
<h2>CORS Vulnerability Verification</h2>
<pre id=”result”>Testing…</pre>
<script>
// Replace with your authorised test API endpoint
const endpoint = ‘https://target.example/api/test-profile’;
// Include credentials from your own test session
fetch(endpoint, {
method: ‘GET’,
credentials: ‘include’
})
.then(response => {
// Check whether the browser allowed JavaScript to read the response
if (!response.ok) {
throw new Error(‘HTTP status: ‘ + response.status);
}
return response.text();
})
.then(data => {
// Display test-account response safely as text
document.getElementById(‘result’).textContent = data;
console.log(‘CORS test: browser successfully read the response.’);
})
.catch(error => {
document.getElementById(‘result’).textContent =
‘Request could not be read: ‘ + error.message;
console.error(‘CORS verification failed:’, error);
});
</script>
</body>
</html>

Here’s how I test it. Save the file as cors-test.html and serve it from a separate origin, such as http://localhost:8080, using a local development server. Keep your authorised test account logged in to the target application in the same browser. Then open the PoC page and observe what happens.

The important part of the code is credentials: 'include'. This tells the browser to include eligible credentials, such as cookies, in the cross-origin request. It does not override cookie restrictions. The target application’s cookie attributes, SameSite policy, Secure requirement and browser third-party cookie settings can still prevent cookies from being sent.

If the browser successfully reads the API response, inspect the returned data. Does it contain account information or other sensitive information belonging to your test user? If yes, you’ve demonstrated something much more meaningful than a reflected header: an untrusted origin can read authenticated data under the tested conditions.

If the browser reports a CORS error, don’t immediately conclude that the application is secure. Go back and check the response headers in Burp, confirm that your test account is authenticated, verify the endpoint and inspect the browser’s Network and Console tabs. Cookie restrictions, missing credentials, an incorrect origin, redirects or other response conditions may explain the failure. Repeater evidence and browser evidence answer different questions, and you need to understand both.

⚠️ Keep your PoC within authorised testing boundaries. Use your own test account, an approved testing domain and endpoints explicitly permitted by the bug bounty programme. Never collect another user’s session data, transmit sensitive responses to an external server or test against unsuspecting users. A local PoC that demonstrates access to your own test data is sufficient to establish the technical impact.

My advice is simple: don’t submit a CORS report just because you managed to reproduce two response headers. Show the request, show the response, demonstrate browser-based access using your own test account, and explain exactly what information becomes readable. That’s the difference between reporting a configuration observation and submitting a convincing security vulnerability.


Severity Assessment: When Is a CORS Bug High vs Informational?

This is where I see many beginners make mistakes in bug bounty reports. They discover that a server reflects an external Origin header, spot Access-Control-Allow-Credentials: true in the response and immediately label the finding Critical. But that’s not how severity assessment works. A CORS misconfiguration is only as serious as the security impact you can actually demonstrate.

When I assess a CORS finding, I focus on three questions: Does the server trust an untrusted origin? Can a browser make a credentialed cross-origin request and allow JavaScript to read the response? And most importantly, what sensitive information does that response expose? Your answers determine whether you’re looking at an informational configuration issue or a genuinely high-impact vulnerability.

CORS SEVERITY ASSESSMENT — PRACTICAL DECISION GUIDE
CASE 1 — REFLECTED ORIGIN WITHOUT CREDENTIALS
ACAO reflects an untrusted origin
ACAC: false or absent
Typical assessment: Informational / Low
No credentialed browser response access demonstrated.
CASE 2 — CREDENTIALS ALLOWED, NO SENSITIVE DATA EXPOSED
Untrusted origin is accepted
ACAC: true
Typical assessment: Low / Context-dependent
The endpoint exposes no meaningful sensitive information.
CASE 3 — CREDENTIALS ALLOWED, SENSITIVE DATA EXPOSED
Untrusted origin is accepted
ACAC: true
Browser JavaScript reads private authenticated data
Typical assessment: High
Examples: personal details, account records or private information.
CASE 4 — CRITICAL BUSINESS OR ACCOUNT IMPACT
Cross-origin access exposes highly sensitive data
Demonstrable serious account or business consequences
Potential assessment: Critical
Requires exceptional, well-demonstrated impact.

Let’s look at what these cases mean in practice. If the server reflects an untrusted origin but does not allow credentialed browser access, you generally don’t have an authenticated data-exposure vulnerability. It may still be worth investigating other consequences, but the reflected header alone is not enough to justify a high severity rating.

Now consider a server that allows credentials but the affected endpoint only returns public information. You may have identified a configuration weakness, but what has an attacker actually gained? If there is no meaningful private information to read, the impact is limited. Don’t inflate the severity simply because the response contains Access-Control-Allow-Credentials: true.

The situation changes when an attacker-controlled origin can read sensitive information from an authenticated user’s browser session. Imagine an API returning private account details, personal information or financial records. If you can reproduce that access using your own test account, you’ve demonstrated a genuine confidentiality impact. Depending on the sensitivity and extent of the exposed information, High severity may be justified.

Critical is a different conversation. It should be reserved for cases where the demonstrated impact is exceptionally serious, such as exposure of highly sensitive information at scale or consequences that enable severe account compromise. A CORS header combination by itself does not make a finding Critical.

The same assessment applies to null-origin and subdomain-based CORS issues. Don’t automatically downgrade them because they require a particular browser context, or upgrade them because the response looks alarming. Evaluate the actual exploitability, browser requirements, affected users and exposed data.

💡 My reporting rule: I never choose severity based on the response headers alone. I first reproduce the issue, identify exactly what data becomes readable, assess the sensitivity of that data and explain the realistic attacker scenario. If I cannot demonstrate meaningful impact, I don’t claim High or Critical. A technically accurate report builds far more credibility with a bug bounty triage team.

One final recommendation: check the bug bounty programme’s own severity policy and use its accepted CVSS or impact-rating methodology. Two programmes can assess the same technical issue differently depending on their assets, user exposure and business risk. Your job is to provide reproducible evidence and a defensible impact assessment, not to chase the highest possible severity label.



Writing a CORS Bug Bounty Report That Gets Paid

Finding a CORS vulnerability is only half the job. The other half is explaining it clearly enough that the triage team can reproduce it, understand the security impact and make a decision without spending hours investigating your submission. I’ve seen technically interesting findings lose momentum simply because the report was vague, missing evidence or exaggerated the impact.

My approach is straightforward: make the report reproducible. Give the triager the exact endpoint, the request header you modified, the response headers you observed and the sensitive information you could read using your authorised test account. If you have a working browser-based PoC, include that evidence too. The goal is to make verification as easy as possible.

Here’s the report structure I recommend. I’ve used fictional domains and placeholder data so you can adapt it to your own authorised findings.

BUG BOUNTY REPORT TEMPLATE — CORS MISCONFIGURATION
Title: CORS Misconfiguration Allows Untrusted Origins to Read Authenticated Account Data on /api/account

Severity: High — subject to programme policy and demonstrated impact

Affected Endpoint:
GET https://api.target.example/api/v1/account

Summary:
The affected API endpoint accepts an untrusted Origin header and reflects its value in the Access-Control-Allow-Origin response header. It also returns Access-Control-Allow-Credentials: true. Using an authorised test account, I confirmed that JavaScript running on a separate untrusted origin could read the authenticated API response. The response contained private account information, including the account email address and other sensitive account details.

Steps to Reproduce:
1. Log in to the authorised test account on target.example.
2. Open the account section and capture the GET /api/v1/account request using Burp Suite Proxy.
3. Send the captured request to Burp Repeater.
4. Add or modify the following request header:
Origin: https://evil.example
5. Send the request and inspect the response headers.
6. Observe that the server returns:
Access-Control-Allow-Origin: https://evil.example
Access-Control-Allow-Credentials: true
7. Verify that the response body contains private information belonging to the authorised test account.
8. Reproduce the browser-based cross-origin read using the attached PoC and the same test account.

Evidence Attached:
– Burp Repeater screenshot showing the modified Origin header.
– Server response showing the reflected origin and credential permission.
– Redacted response body demonstrating the exposed data fields.
– Browser PoC screenshot confirming successful cross-origin response reading.

Proof of Concept:
A minimal JavaScript PoC was executed from a separate origin against the authorised test account. The browser successfully read the authenticated API response. No third-party user data was accessed or collected.

Security Impact:
An attacker could potentially host a malicious webpage and trick an authenticated user into visiting it. If the user’s browser sends eligible credentials and the vulnerable endpoint exposes private account information, JavaScript on the attacker’s origin may read that information. The demonstrated impact in this report is unauthorised cross-origin access to authenticated account data.

Remediation:
– Maintain an explicit server-side allowlist of trusted origins.
– Compare complete, normalised origin values rather than using substring or unsafe suffix matching.
– Never blindly reflect the incoming Origin header.
– Return Access-Control-Allow-Credentials: true only where credentialed cross-origin access is genuinely required.
– Avoid allowing the null origin unless there is a documented security requirement.
– Validate CORS behaviour across all affected API endpoints and browser contexts.

Now let me explain why I structure reports this way. The title tells the triager what is wrong and what security impact to expect. The summary gives them the complete vulnerability in a few sentences. The reproduction steps remove guesswork. And the evidence demonstrates that the issue is not just a suspicious response header but a browser-accessible security weakness.

Pay particular attention to the impact section. Don’t simply write that an attacker can steal cookies or take over accounts unless you’ve actually demonstrated that consequence. Explain which information becomes readable, under what authentication conditions and what an attacker could realistically do with it. A precise impact statement is much more convincing than dramatic claims.

Finally, keep your screenshots clean. Highlight the modified Origin header in the request, the two relevant CORS response headers and the affected response fields. Redact session cookies, authorisation tokens, personal information and other secrets. Never include another user’s private data in your submission.

💡 My report-writing rule: Give the triager enough information to reproduce your finding in under two minutes. Exact endpoint, exact request, exact response, working PoC and clearly demonstrated impact. If any one of these is missing, improve the report before submitting it.

Remember, a good bug bounty report doesn’t just tell a programme that something is broken. It proves what is broken, shows how to reproduce it and explains why fixing it matters. That’s how you build credibility with triage teams and submit reports that stand a much better chance of being accepted.

⚡ EXERCISE 3 — WRITE THE REPORT (15 MIN)

Build a complete report from your PortSwigger lab finding:

  1. Using the PortSwigger CORS lab from Exercise 2 as your target, complete the report template above with the real endpoint URL, the exact response headers you saw, and the real data the endpoint returned.
  2. Rate the severity using the decision tree above. Does the endpoint return sensitive data? Is Allow-Credentials: true present? What CVSS score do you assign?
  3. Write a one-paragraph Impact section that explains, in plain English for a non-technical manager, what an attacker who exploited this could actually do to a victim user. No jargon, just consequence.
✅ What you just learned: the plain-English impact paragraph is what gets CORS findings triaged seriously. A technical audience sees the headers and understands. A product manager or CISO who controls the bounty decision understands “an attacker can silently read your bank balance by getting you to visit their website.” Write for both audiences in the same report.
📸 Share your one-paragraph impact statement in #day-31-cors.

💰 Quick check: you test an endpoint and get Access-Control-Allow-Origin: * but no Access-Control-Allow-Credentials header. What severity do you assign?




📋 Day 31 reference card

Origin: https://evil.comTest for reflected origin — add to Repeater request
Origin: nullTest for null origin whitelist
Origin: https://eviltarget.comTest for suffix/prefix validation bypass
Allow-Credentials: trueThe header that makes CORS misconfiguration exploitable
credentials: ‘include’The fetch() flag that sends cookies cross-origin in PoC
Hashcat -m 5600 = NTLMv2Reminder: today’s CORS PoC uses JS fetch, not Hashcat!

✅ Mark Day 31 complete

You can find, test and report all three CORS misconfiguration patterns — and you know exactly when Allow-Credentials: true turns an Informational into a High.

Tomorrow — Day 32: OAuth Token Leakage, and the mistakes that hand you someone else’s account.

❓ Frequently asked questions

What is a CORS misconfiguration?
When a server incorrectly grants cross-origin access to untrusted origins, either by reflecting any Origin header value, whitelisting the null origin, or using flawed suffix matching. Combined with Access-Control-Allow-Credentials: true, it allows attacker pages to read authenticated API responses using the victim’s session cookies.
Why is Access-Control-Allow-Credentials: true the key factor?
Without it, the browser refuses to include cookies in cross-origin requests, and ignores the response from credentialed endpoints. The misconfiguration only becomes exploitable when both the origin is trusted AND credentials are allowed — that combination lets the attacker’s page read the victim’s authenticated data.
What is the null origin attack?
Sandboxed iframes have a null origin in the browser. If a server whitelists the null origin with Allow-Credentials, an attacker can host a sandboxed iframe that sends credentialed cross-origin requests and reads the authenticated response — without needing a real domain that matches the target’s CORS whitelist.
Is a wildcard Access-Control-Allow-Origin always a bug?
Not by itself. A wildcard without Allow-Credentials is often intentional for public APIs. The browser spec also prevents combining * with Allow-Credentials: true. The misconfiguration is when a server dynamically reflects specific origin values while also allowing credentials — that’s not the same as a static wildcard.
How do I fix CORS misconfiguration?
Maintain a server-side allowlist of exact trusted origins. Never reflect the incoming Origin header directly. Validate the full origin string, not a suffix. Never combine Access-Control-Allow-Credentials: true with a wildcard or dynamically reflected origin. Set the minimum necessary CORS headers — most APIs don’t need Allow-Credentials at all.
Where can I practice CORS testing safely?
PortSwigger Web Security Academy has free CORS labs covering reflected origin, null origin, and trusted subdomain attacks. They’re fully authorised, realistic, and include the JavaScript PoC chain. That’s where the exercises in this lesson are designed to run.
← Previous
Day 30: Deserialization Bug Bounty
Next →
Day 32: OAuth Token Leakage

📚 Further reading

ME
Mr Elite
I filed a CORS report that got marked Informational because the triage team only checked the origin reflection and not the Allow-Credentials header — they assumed it wasn’t exploitable. I added a 45-second screen recording showing the JavaScript PoC reading the victim account’s email and balance in the browser console. Severity went to High in the same thread, same day. The evidence was always there. The problem was the triager assumed the standard “wildcard is safe” reasoning applied. Your job in a report is to make it impossible for that assumption to survive. The PoC is not optional on a High; it’s what turns your finding from “plausible” to “proven.”

⚡
Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free
Lokesh N. Singh aka Mr Elite
Lokesh N. Singh aka Mr Elite
Founder, Securityelites · AI Red Team Educator
Founder of Securityelites and creator of the SE-ARTCP credential. Working penetration tester focused on AI red team, prompt injection research, and LLM security education.
About Lokesh ->

Leave a Comment

Your email address will not be published. Required fields are marked *