Skip to content
Back to skills

Set Up Security Headers

ASecurity

Use when hardening a frontend SPA's delivery — defines a Content-Security-Policy and standard security headers delivered at the edge via Netlify, dependency hygiene via Dependabot, and an honest note on the XSS surface.

  • 5 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 9, 2026
developmentbashreactvuegitapifrontendsecurity

Works with

  • api

Security analysis

A96/100
  • mediumUses curl or wget to download content

Pro scans all 2 files and shows the line behind each finding

Scanned October 9, 2026

npx -y skills add VelimirMueller/vlm-code-context-mcp --skill set-up-security-headers --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Set Up Security Headers?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Set Up Security Headers
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/velimirmueller-set-up-security-headers/badge)](https://www.skillsdirectory.com/skills/velimirmueller-set-up-security-headers)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: set-up-security-headers
description: Use when hardening a frontend SPA's delivery — defines a Content-Security-Policy and standard security headers delivered at the edge via Netlify, dependency hygiene via Dependabot, and an honest note on the XSS surface.
---

# Set Up Security Headers

Security headers are delivered by the host, not the bundle. This skill writes a strict, SPA-appropriate header set for Netlify and wires the CSP's `connect-src` to the origins the app actually calls.

## 1. Audit current state
```bash
ls netlify.toml public/_headers .github/dependabot.yml 2>/dev/null
grep -in "content-security-policy\|strict-transport" netlify.toml public/_headers 2>/dev/null
grep -n "VITE_API_URL\|VITE_REALTIME_URL" src/libs/env.ts 2>/dev/null   # origins for connect-src
```
**Prerequisites:** a Netlify deploy (see `configure-ci`). Recommended: `validate-env` (the CSP reads `VITE_API_URL` / `VITE_REALTIME_URL`).

## 2. Decide
- No headers → full setup. Partial → add the missing headers/directives. Present → confirm `connect-src` covers current API + realtime origins.

## 3. The header block (Netlify)
Add to `netlify.toml` (create if absent — this is the `[[headers]]` block; `configure-ci` owns the `[build]` block, so merge, don't overwrite):
```toml
[[headers]]
  for = "/*"
  [headers.values]
    Content-Security-Policy = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' https://api.example.com wss://realtime.example.com; frame-ancestors 'none'; base-uri 'self'; object-src 'none'"
    Strict-Transport-Security = "max-age=31536000; includeSubDomains; preload"
    X-Content-Type-Options = "nosniff"
    Referrer-Policy = "strict-origin-when-cross-origin"
    Permissions-Policy = "camera=(), microphone=(), geolocation=()"
```
Replace `https://api.example.com` / `wss://realtime.example.com` with the **origins** of `VITE_API_URL` / `VITE_REALTIME_URL` (scheme + host, no path). Drop the `wss:` origin if realtime isn't set up.

## 4. CSP notes for a Vite SPA
- Vite emits **external** scripts in prod, so `script-src 'self'` needs no `'unsafe-inline'`. (These headers apply to the deployed build; the dev server is looser.)
- `style-src` keeps `'unsafe-inline'` because Tailwind/runtime styles inject inline `<style>`. To drop it, adopt a nonce/hash — see `security-patterns.md`.
- `connect-src` breaks silently: omit your API or `wss://` origin and those requests fail with a console CSP error. That's why it reads from the env seam.

## 5. Dependency hygiene
`.github/dependabot.yml`:
```yaml
version: 2
updates:
  - package-ecosystem: npm
    directory: "/"
    schedule:
      interval: weekly
    groups:
      minor-and-patch:
        update-types: [minor, patch]
```
Pair with a `pnpm audit` step in CI (`configure-ci`). Automation proposes; a human approves each bump.

## 6. The XSS surface (the honest note)
React and Vue escape interpolated values by default. The real hole is **`dangerouslySetInnerHTML` (React) / `v-html` (Vue)** — they bypass escaping. Avoid them; if unavoidable, sanitize with DOMPurify first. A strict CSP is defense-in-depth, not a substitute.

## 7. Verify
```bash
# after a deploy preview is live:
curl -sI https://<deploy-preview-url>/ | grep -i "content-security-policy\|strict-transport"
```
Load the app: the console shows **no** CSP violations (every API / realtime / font / image origin is allowed). Grade it at securityheaders.com.

## References
- ./security-patterns.md — edge-vs-meta delivery, the `connect-src`-from-env rule, the inline-style nonce path, dependency hygiene, the XSS surface, and other hosts.
- ../validate-env/SKILL.md — the `env` seam supplying the `connect-src` origins.
- ../configure-ci/SKILL.md — owns the `netlify.toml` `[build]` block and the `pnpm audit` step.

Files in this skill

  • SKILL.md3.8 KB
  • security-patterns.md2.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.