open-cors-anti-pattern

open-cors-anti-pattern

Security anti-pattern for open Cross-Origin Resource Sharing (CORS) policies (CWE-942). Use when generating or reviewing server configurations, API backends, or any code that sets CORS headers. Detects overly permissive Access-Control-Allow-Origin headers, including wildcard, null origin, and reflected origin.

2estrelas
1forks
Atualizado 1/22/2026
SKILL.md
readonlyread-only
name
"open-cors-anti-pattern"
description

"Security anti-pattern for open Cross-Origin Resource Sharing (CORS) policies (CWE-942). Use when generating or reviewing server configurations, API backends, or any code that sets CORS headers. Detects overly permissive Access-Control-Allow-Origin headers, including wildcard, null origin, and reflected origin."

Open CORS Policy Anti-Pattern

Severity: Medium

Summary

Cross-Origin Resource Sharing (CORS) is a browser security feature that controls how web pages from one domain can request resources from another domain. A misconfigured, overly permissive CORS policy is a common vulnerability. This anti-pattern occurs when a server responds with Access-Control-Allow-Origin: * or dynamically reflects the client's Origin header. This allows any website on the internet to make authenticated requests to your application on behalf of your users, potentially leading to data theft and unauthorized actions.

The Anti-Pattern

The anti-pattern is configuring the Access-Control-Allow-Origin header to a value that is too permissive, such as the wildcard (*) or reflecting any value sent by the client in the Origin header.

BAD Code Example

# VULNERABLE: The server reflects any Origin header, or uses a wildcard with credentials.
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.after_request
def add_cors_headers(response):
    # DANGEROUS: Reflecting the Origin header.
    # An attacker's site (https://evil.com) can now make requests.
    origin = request.headers.get('Origin')
    if origin:
        response.headers['Access-Control-Allow-Origin'] = origin

    # DANGEROUS: Wildcard `*` combined with `Allow-Credentials`.
    # Most browsers block this, but it's a critical misconfiguration.
    # response.headers['Access-Control-Allow-Origin'] = '*'
    # response.headers['Access-Control-Allow-Credentials'] = 'true'

    return response

@app.route("/api/user/profile")
def get_profile():
    # This endpoint is intended to be called by your frontend application.
    # It relies on the user's session cookie for authentication.
    user = get_user_from_session()
    return jsonify(user.to_dict())

# Attack Scenario:
# 1. A logged-in user of your site visits https://evil.com.
# 2. A script on evil.com makes a `fetch` request to `https://yourapp.com/api/user/profile`.
# 3. Because of the permissive CORS policy, the browser allows this request,
#    and importantly, it attaches the user's session cookie.
# 4. Your server receives a valid, authenticated request and responds with the user's sensitive profile data.
# 5. The script on evil.com now has the user's data and can send it to the attacker.

GOOD Code Example

# SECURE: Maintain a strict allowlist of trusted origins.
from flask import Flask, request, jsonify

app = Flask(__name__)

# Define a strict allowlist of origins that are permitted to access your API.
ALLOWED_ORIGINS = {
    "https://www.yourapp.com",
    "https://yourapp.com",
    "https://staging.yourapp.com"
}

@app.after_request
def add_secure_cors_headers(response):
    origin = request.headers.get('Origin')
    if origin in ALLOWED_ORIGINS:
        # Only set the header if the origin is in the trusted list.
        response.headers['Access-Control-Allow-Origin'] = origin
        response.headers['Access-Control-Allow-Credentials'] = 'true'
        # Vary header tells caches that the response depends on the Origin.
        response.headers['Vary'] = 'Origin'
    return response

@app.route("/api/user/profile")
def get_profile_secure():
    user = get_user_from_session()
    return jsonify(user.to_dict())

# Now, when a script from https://evil.com tries to make a request,
# the `origin` is not in the `ALLOWED_ORIGINS` set, so no CORS headers are sent.
# The browser's same-origin policy blocks the request, protecting the user's data.

Detection

  • Use browser developer tools: Open the "Network" tab, make a cross-origin request to your API, and inspect the response headers. Look for Access-Control-Allow-Origin. Is it *? Does it match the Origin of your request even if that origin is untrusted?
  • Use curl: Make a request and set a custom Origin header to see if the server reflects it:
    curl -H "Origin: https://evil.com" -I https://yourapp.com/api/some-endpoint
    Check if the response contains Access-Control-Allow-Origin: https://evil.com.
  • Review CORS configuration: Check your application's code or framework configuration for how CORS headers are being set. Look for wildcards or reflected origins.

Prevention

  • [ ] Maintain a strict allowlist of trusted origins. This is the most critical step.
  • [ ] Never reflect the user-provided Origin header without validating it against the allowlist first.
  • [ ] Do not use the wildcard (*) for Access-Control-Allow-Origin on any endpoint that requires authentication (e.g., uses cookies or Authorization headers). A wildcard is only safe for truly public, unauthenticated resources.
  • [ ] Set Access-Control-Allow-Credentials to true only when necessary and only for origins on your allowlist.
  • [ ] Add the Vary: Origin header to tell caches that the response is origin-dependent. This prevents a cached response intended for a trusted origin from being served to a malicious one.

Related Security Patterns & Anti-Patterns

References

You Might Also Like

Related Skills

create-pr

create-pr

170Kdev-devops

Creates GitHub pull requests with properly formatted titles that pass the check-pr-title CI validation. Use when creating PRs, submitting changes for review, or when the user says /pr or asks to create a pull request.

n8n-io avatarn8n-io
Obter

Guide for performing Chromium version upgrades in the Electron project. Use when working on the roller/chromium/main branch to fix patch conflicts during `e sync --3`. Covers the patch application workflow, conflict resolution, analyzing upstream Chromium changes, and proper commit formatting for patch fixes.

electron avatarelectron
Obter
pr-creator

pr-creator

92Kdev-devops

Use this skill when asked to create a pull request (PR). It ensures all PRs follow the repository's established templates and standards.

google-gemini avatargoogle-gemini
Obter
clawdhub

clawdhub

87Kdev-devops

Use the ClawdHub CLI to search, install, update, and publish agent skills from clawdhub.com. Use when you need to fetch new skills on the fly, sync installed skills to latest or a specific version, or publish new/updated skill folders with the npm-installed clawdhub CLI.

moltbot avatarmoltbot
Obter
tmux

tmux

87Kdev-devops

Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.

moltbot avatarmoltbot
Obter
create-pull-request

create-pull-request

57Kdev-devops

Create a GitHub pull request following project conventions. Use when the user asks to create a PR, submit changes for review, or open a pull request. Handles commit analysis, branch management, and PR creation using the gh CLI tool.

cline avatarcline
Obter