Phy Cors Audit

TotalClaw 作者 Canlah AI v1.0.2

CORS(跨域资源共享)配置错误审核员。使用精心设计的 Origin 标头探测任何 API 端点,以检测最危险的 CORS 漏洞 - 反映任意来源(任何 Attacker.com 都获得 CORS 批准)、Access-Control-Allow-Credentials:true 并带有通配符 ACAO、允许 null-Origin(iframe/file:// 绕过)、子域正则表达式绕过(evil.myapp.com 通行证)、缺少 Vary:Origin(CDN 缓存中毒)以及允许的预检响应。还扫描源代码以查找不安全的 CORS 中间件模式(Express/FastAPI/Go/Rails/Django/Spring)。为您的特定堆栈生成正确的 CORS 配置。通过curl 适用于任何实时URL — 零外部API。在“CORS 错误”、“CORS 错误配置”、“Access-Control-Allow-Origin”、“cors 策略”、“预检”、“cors 阻止”、“/cors-audit”上触发。

源码 ↗

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install totalclaw:phy041~phy-cors-audit
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Aphy041~phy-cors-audit/file -o phy-cors-audit.md
Git 仓库获取源码
git clone https://github.com/openclaw/skills/commit/e535d075cc37190b1c46932a60278df197f5ec1c
## 概述(中文)

CORS(跨域资源共享)配置错误审核员。使用精心设计的 Origin 标头探测任何 API 端点,以检测最危险的 CORS 漏洞 - 反映任意来源(任何 Attacker.com 都获得 CORS 批准)、Access-Control-Allow-Credentials:true 并带有通配符 ACAO、允许 null-Origin(iframe/file:// 绕过)、子域正则表达式绕过(evil.myapp.com 通行证)、缺少 Vary:Origin(CDN 缓存中毒)以及允许的预检响应。还扫描源代码以查找不安全的 CORS 中间件模式(Express/FastAPI/Go/Rails/Django/Spring)。为您的特定堆栈生成正确的 CORS 配置。通过curl 适用于任何实时URL — 零外部API。在“CORS 错误”、“CORS 错误配置”、“Access-Control-Allow-Origin”、“cors 策略”、“预检”、“cors 阻止”、“/cors-audit”上触发。

## 原文

# CORS Audit

`Access to fetch at 'https://api.myapp.com' from origin 'https://evil.com' has been set with CORS policy: No 'Access-Control-Allow-Origin'`

Then you add `Access-Control-Allow-Origin: *` and it works. Except now your API accepts requests from every site on the internet, with every user's credentials, if you forgot to check the credentials flag.

This skill probes your CORS configuration with crafted Origin headers, finds the misconfigurations that let attackers run authenticated cross-origin requests against your users, and generates the correct allow-list config for your stack.

**Works against any live URL via curl. Scans Express/FastAPI/Go/Rails/Django source. Zero external API.**

---

## Trigger Phrases

- "CORS error", "CORS blocked", "CORS not working"
- "CORS misconfiguration", "cors security"
- "Access-Control-Allow-Origin", "ACAO"
- "cors policy", "preflight OPTIONS"
- "cors wildcard", "cors credentials"
- "/cors-audit"

---

## How to Provide Input

```bash
# Option 1: Probe a live API endpoint
/cors-audit https://api.myapp.com/users

# Option 2: Probe with specific origin
/cors-audit https://api.myapp.com --origin https://evil.com

# Option 3: Full probe battery (all known bypasses)
/cors-audit https://api.myapp.com --full

# Option 4: Scan source code for CORS misconfigurations
/cors-audit --scan src/

# Option 5: Generate correct CORS config for your stack
/cors-audit --generate express --allowed-origins https://myapp.com,https://staging.myapp.com

# Option 6: CI mode (exit 1 on critical findings)
/cors-audit https://api.myapp.com --ci

# Option 7: Audit multiple endpoints at once
/cors-audit --endpoints /api/users,/api/orders,/api/admin --base https://api.myapp.com
```

---

## Step 1: Probe CORS Configuration

```python
import subprocess
import re
from dataclasses import dataclass, field
from typing import Optional
from urllib.parse import urlparse


@dataclass
class CorsProbeResult:
    probe_name: str
    origin_sent: str
    acao: Optional[str]          # Access-Control-Allow-Origin
    acac: Optional[str]          # Access-Control-Allow-Credentials
    acam: Optional[str]          # Access-Control-Allow-Methods
    acah: Optional[str]          # Access-Control-Allow-Headers
    vary: Optional[str]          # Vary header
    status_code: int
    is_vulnerable: bool
    severity: str
    issue: str
    fix: str


def probe_cors(url: str, origin: str, method: str = 'GET') -> dict:
    """Send a single CORS probe and return response headers."""
    result = subprocess.run(
        ['curl', '-sI', '-X', method, url,
         '-H', f'Origin: {origin}',
         '-H', 'Content-Type: application/json',
         '--max-time', '10',
         '--user-agent', 'CorsAuditor/1.0'],
        capture_output=True, text=True
    )
    headers = {}
    status_code = 200
    for line in result.stdout.splitlines():
        if line.startswith('HTTP/'):
            try:
                status_code = int(line.split()[1])
            except (IndexError, ValueError):
                pass
        elif ':' in line:
            key, _, value = line.partition(':')
            headers[key.strip().lower()] = value.strip()
    return {'headers': headers, 'status_code': status_code, 'raw': result.stdout}


def run_cors_battery(url: str) -> list[CorsProbeResult]:
    """
    Run the full battery of CORS probes against a URL.
    Tests all known CORS misconfiguration patterns.
    """
    parsed = urlparse(url)
    base_domain = parsed.netloc  # e.g. api.myapp.com

    # Derive legitimate origin (for baseline)
    legitimate_origin = f'{parsed.scheme}://{base_domain.replace("api.", "")}'

    # Build the probe set
    probes = [
        {
            'name': 'arbitrary_origin_evil',
            'origin': 'https://evil.com',
            'description': 'Random attacker origin',
        },
        {
            'name': 'null_origin',
            'origin': 'null',
            'description': 'null origin (file://, sandboxed iframe)',
        },
        {
            'name': 'subdomain_bypass',
            'origin': f'https://evil.{base_domain}',
            'description': f'Subdomain of target: evil.{base_domain}',
        },
        {
            'name': 'prefix_bypass',
            'origin': f'https://{base_domain}.evil.com',
            'description': f'Domain that contains target as prefix: {base_domain}.evil.com',
        },
        {
            'name': 'http_downgrade',
            'origin': f'http://{base_domain}',
            'description': f'HTTP version of same domain: http://{base_domain}',
        },
        {
            'name': 'legitimate_origin',
            'origin': legitimate_origin,
            'description': f'Legitimate origin: {legitimate_origin}',
        },
        {
            'name': 'wildcard_check',
            'origin': 'https://completely-unrelated.com',
            'description': 'Completely unrelated domain',
        },
    ]

    results = []

    for probe in probes:
        resp = probe_cors(url, probe['origin'])
        headers = resp['headers']
        acao = headers.get('access-control-allow-origin')
        acac = headers.get('access-control-allow-credentials', '').lower()
        vary = headers.get('vary', '')

        # Analyze the response
        is_vulnerable = False
        severity = 'INFO'
        issue = ''
        fix = ''

        if not acao:
            # No CORS headers — either not configured or blocked
            if probe['name'] == 'legitimate_origin':
                issue = 'No CORS headers returned for legitimate origin'
                severity = 'INFO'
            else:
                issue = 'Request blocked (no ACAO header) ✅'
                severity = 'PASS'
        elif acao == '*':
            if acac == 'true':
                # IMPOSSIBLE combination per spec, but some servers misconfigure this
                is_vulnerable = True
                severity = 'CRITICAL'
                issue = 'Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true — browsers reject this, but some HTTP clients do not'
                fix = 'Never use wildcard with credentials. Specify exact origins: Access-Control-Allow-Origin: https://myapp.com'
            else:
                if probe['name'] in ('arbitrary_origin_evil', 'wildcard_check'):
                    severity = 'HIGH'
                    is_vulnerable = True
                    issue = 'Wildcard ACAO (*) — any origin can make unauthenticated cross-origin requests'
                    fix = 'Replace * with an explicit allowlist. Wildcard is safe only for fully public, unauthenticated APIs.'
                else:
                    severity = 'MEDIUM'
                    issue = 'Wildcard ACAO — acceptable only if API requires no authentication'
                    fix = 'Confirm this endpoint has no authentication. If it does, restrict ACAO to specific origins.'
        elif acao == probe['origin']:
            # Origin is reflected — check if this is intentional
            if probe['name'] == 'legitimate_origin':
                severity = 'PASS'
                issue = f'Origin correctly reflected for legitimate origin ✅'
                # Check for Vary: Origin
                if 'origin' not in vary.lower():
                    severity = 'MEDIUM'
                    is_vulnerable = True
                    issue = 'ACAO reflects Origin but Vary: Origin missing — CDN/proxy may cache and serve wrong CORS response'
                    fix = 'Add Va