<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: implementing-api-security-headers
description: >-
  Implement and validate HTTP security headers for APIs including CORS
  policies, Content-Type enforcement, HSTS, CSP for API responses, and
  anti-caching controls to prevent data leakage and cross-origin abuse.
domain: cybersecurity
subdomain: api-security
tags:
  - security-headers
  - api-security
  - cors
  - hsts
  - content-security
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1189", "T1557"]
  owasp-api: ["API8"]
  tools: ["curl", "burp-suite", "nuclei", "securityheaders.com"]
---

# Implementing API Security Headers

## Overview

Missing or misconfigured security headers expose APIs to cross-origin
attacks, content-type confusion, caching of sensitive data, and
clickjacking. CORS misconfigurations are particularly dangerous for APIs,
allowing unauthorized cross-origin access to authenticated endpoints.

## Prerequisites

- Tools: ["curl", "burp-suite", "nuclei", "securityheaders.com"]
- Access to API server/gateway configuration
- List of allowed origins for CORS
- Authorized testing engagement with written scope

## Key Concepts

- **CORS**: Cross-Origin Resource Sharing — controls which origins can call the API
- **HSTS**: HTTP Strict Transport Security — forces HTTPS connections
- **Content-Type enforcement**: Prevents MIME sniffing attacks
- **Cache-Control**: Prevents caching of sensitive API responses

## Workflow

### Step 1: Audit Current Security Headers

```bash
# Check all security headers on API response
curl -sI -H "Authorization: Bearer $TOKEN" \
  https://target.com/api/users/me | grep -iE \
  'strict-transport|content-security|x-content-type|x-frame|x-xss|cache-control|cors|access-control'

# Comprehensive header audit
HEADERS=(
  "Strict-Transport-Security"
  "Content-Security-Policy"
  "X-Content-Type-Options"
  "X-Frame-Options"
  "X-XSS-Protection"
  "Cache-Control"
  "Pragma"
  "Access-Control-Allow-Origin"
  "Access-Control-Allow-Credentials"
  "Referrer-Policy"
  "Permissions-Policy"
)

for H in "${HEADERS[@]}"; do
  VALUE=$(curl -sI -H "Authorization: Bearer $TOKEN" \
    https://target.com/api/users/me | grep -i "^$H:" | head -1)
  if [ -z "$VALUE" ]; then
    echo "MISSING: $H"
  else
    echo "PRESENT: $VALUE"
  fi
done
```

### Step 2: Test CORS Configuration

```bash
# Test with arbitrary origin
curl -sI -H "Origin: https://evil.com" \
  -H "Authorization: Bearer $TOKEN" \
  https://target.com/api/users/me | grep -i 'access-control'

# Test null origin
curl -sI -H "Origin: null" \
  https://target.com/api/users/me | grep -i 'access-control'

# Test origin reflection (wildcard CORS)
curl -sI -H "Origin: https://attacker.com" \
  https://target.com/api/data | grep -i 'access-control-allow-origin'
# If response contains "https://attacker.com" = VULNERABLE

# Test credentials with wildcard
curl -sI -H "Origin: https://evil.com" \
  -H "Authorization: Bearer $TOKEN" \
  https://target.com/api/users/me | \
  grep -iE 'access-control-allow-(origin|credentials)'
# allow-origin: * with allow-credentials: true = CRITICAL

# Test preflight request
curl -sI -X OPTIONS \
  -H "Origin: https://evil.com" \
  -H "Access-Control-Request-Method: DELETE" \
  -H "Access-Control-Request-Headers: Authorization" \
  https://target.com/api/users/123
```

### Step 3: Test Cache-Control for Sensitive Endpoints

```bash
# Verify no-store on sensitive endpoints
SENSITIVE_ENDPOINTS=(
  "/api/users/me"
  "/api/users/me/payment-methods"
  "/api/users/me/sessions"
  "/api/admin/config"
)

for EP in "${SENSITIVE_ENDPOINTS[@]}"; do
  CACHE=$(curl -sI -H "Authorization: Bearer $TOKEN" \
    "https://target.com$EP" | grep -i 'cache-control')
  echo "$EP: ${CACHE:-MISSING Cache-Control}"
done
# Expected: Cache-Control: no-store, no-cache, must-revalidate
```

### Step 4: Validate Content-Type Enforcement

```bash
# Send request with wrong Content-Type
curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: text/plain" \
  -d '{"name":"test"}' \
  https://target.com/api/users

# Test without Content-Type header
curl -s -X POST \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"name":"test"}' \
  https://target.com/api/users

# Check X-Content-Type-Options
curl -sI https://target.com/api/data | grep -i 'x-content-type-options'
# Expected: X-Content-Type-Options: nosniff
```

## Detection Opportunities

| Signal | Source | Description |
|--------|--------|-------------|
| CORS requests from unknown origins | API gateway | Unexpected Origin headers |
| Missing security headers | Monitoring | Header compliance drift |
| Cached sensitive responses | Proxy logs | Sensitive data in cache |
| Content-Type mismatches | WAF | Wrong Content-Type on API requests |

```yaml
title: CORS Misconfiguration — Arbitrary Origin Reflected
id: c9d0e1f2-a3b4-5678-cdef-789012345678
status: experimental
description: Detects API responses reflecting arbitrary origins in CORS headers
logsource:
  category: webserver
detection:
  selection:
    cs-header-Origin|re: 'https?://(?!target\.com)'
    sc-header-Access-Control-Allow-Origin|re: 'https?://'
    sc-header-Access-Control-Allow-Credentials: 'true'
  condition: selection
falsepositives:
  - Explicitly allowed partner domains
level: high
tags:
  - attack.t1189
  - attack.initial_access
```

## Verification

- [ ] CORS allows only explicitly listed origins (no wildcard with credentials)
- [ ] HSTS enabled with max-age >= 31536000 and includeSubDomains
- [ ] X-Content-Type-Options: nosniff on all responses
- [ ] Cache-Control: no-store on sensitive endpoints
- [ ] Content-Type strictly validated on request parsing
- [ ] Server header does not leak version information

## References

- [OWASP API8:2023 — Security Misconfiguration](https://owasp.org/API-Security/editions/2023/en/0xa8-security-misconfiguration/)
- [MDN — CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
- [OWASP Secure Headers Project](https://owasp.org/www-project-secure-headers/)
