secure-headers-csp-builder

Secure Headers & CSP Builder

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "secure-headers-csp-builder" with this command: npx skills add monkey1sai/openai-cli/monkey1sai-openai-cli-secure-headers-csp-builder

Secure Headers & CSP Builder

Add security headers safely without breaking functionality.

Essential Security Headers

// middleware/security-headers.ts import { Request, Response, NextFunction } from "express";

export function securityHeaders( req: Request, res: Response, next: NextFunction ) { // Prevent clickjacking res.setHeader("X-Frame-Options", "DENY");

// Prevent MIME sniffing res.setHeader("X-Content-Type-Options", "nosniff");

// XSS Protection (legacy browsers) res.setHeader("X-XSS-Protection", "1; mode=block");

// Referrer Policy res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");

// Permissions Policy (replaces Feature-Policy) res.setHeader( "Permissions-Policy", "camera=(), microphone=(), geolocation=(self), payment=()" );

// HSTS - Force HTTPS (only in production) if (process.env.NODE_ENV === "production") { res.setHeader( "Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload" ); }

next(); }

Content Security Policy (CSP)

Phase 1: Report-Only Mode

// config/csp-report-only.ts export const cspReportOnly = { "default-src": ["'self'"], "script-src": [ "'self'", "'report-sample'", "https://cdn.jsdelivr.net", "https://www.googletagmanager.com", ], "style-src": ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"], "img-src": ["'self'", "data:", "https:"], "font-src": ["'self'", "https://fonts.gstatic.com"], "connect-src": ["'self'", "https://api.example.com"], "frame-ancestors": ["'none'"], "base-uri": ["'self'"], "form-action": ["'self'"], "report-uri": ["/api/csp-report"], };

function formatCSP(policy: Record<string, string[]>): string { return Object.entries(policy) .map(([key, values]) => ${key} ${values.join(" ")}) .join("; "); }

// Apply report-only header app.use((req, res, next) => { res.setHeader( "Content-Security-Policy-Report-Only", formatCSP(cspReportOnly) ); next(); });

CSP Violation Reporter

// routes/csp-report.ts app.post( "/api/csp-report", express.json({ type: "application/csp-report" }), (req, res) => { const violation = req.body["csp-report"];

console.error("CSP Violation:", {
  documentUri: violation["document-uri"],
  violatedDirective: violation["violated-directive"],
  blockedUri: violation["blocked-uri"],
  sourceFile: violation["source-file"],
  lineNumber: violation["line-number"],
});

// Store in monitoring system
trackCSPViolation({
  directive: violation["violated-directive"],
  blockedUri: violation["blocked-uri"],
  userAgent: req.headers["user-agent"],
  timestamp: new Date(),
});

res.status(204).send();

} );

Phase 2: Enforce Mode

// config/csp-enforce.ts export const cspEnforce = { "default-src": ["'self'"], "script-src": [ "'self'", // Add nonces for inline scripts "'nonce-{NONCE}'", "https://cdn.jsdelivr.net", "https://www.googletagmanager.com", ], "style-src": [ "'self'", // Replace unsafe-inline with nonces "'nonce-{NONCE}'", "https://fonts.googleapis.com", ], "img-src": ["'self'", "data:", "https:"], "font-src": ["'self'", "https://fonts.gstatic.com"], "connect-src": ["'self'", "https://api.example.com"], "frame-ancestors": ["'none'"], "base-uri": ["'self'"], "form-action": ["'self'"], "upgrade-insecure-requests": [], };

// Generate nonce for each request app.use((req, res, next) => { const nonce = crypto.randomBytes(16).toString("base64"); res.locals.cspNonce = nonce;

const policy = formatCSP(cspEnforce).replace(/{NONCE}/g, nonce);

res.setHeader("Content-Security-Policy", policy); next(); });

Nonce Implementation

// views/index.ejs <!DOCTYPE html> <html> <head> <!-- Inline script with nonce --> <script nonce="<%= cspNonce %>"> console.log('This script is allowed by CSP'); </script>

<!-- Inline style with nonce --> <style nonce="<%= cspNonce %>"> body { background: white; } </style> </head> <body> <h1>Secure Page</h1> </body> </html>

Helmet.js Integration

// Using Helmet for comprehensive security headers import helmet from "helmet";

app.use( helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"], scriptSrc: ["'self'", "'nonce-{NONCE}'"], styleSrc: ["'self'", "'nonce-{NONCE}'"], imgSrc: ["'self'", "data:", "https:"], connectSrc: ["'self'", "https://api.example.com"], fontSrc: ["'self'", "https://fonts.gstatic.com"], objectSrc: ["'none'"], mediaSrc: ["'self'"], frameSrc: ["'none'"], }, }, hsts: { maxAge: 31536000, includeSubDomains: true, preload: true, }, frameguard: { action: "deny", }, xssFilter: true, noSniff: true, referrerPolicy: { policy: "strict-origin-when-cross-origin", }, }) );

Rollout Plan

CSP Rollout Plan

Week 1: Report-Only Mode

  • Deploy CSP in report-only mode
  • Monitor violation reports
  • Identify problematic resources
  • Whitelist legitimate sources

Week 2: Analysis

  • Analyze 1 week of violations
  • Update CSP policy based on reports
  • Fix inline scripts/styles
  • Test on staging

Week 3: Staged Rollout

  • Enable enforcement for 10% of traffic
  • Monitor error rates
  • Check user reports
  • Adjust policy if needed

Week 4: Full Enforcement

  • Enable for 50% of traffic
  • Verify no issues
  • Enable for 100% of traffic
  • Keep report-only header for monitoring

Testing CSP

// tests/csp.test.ts import { describe, it, expect } from "vitest"; import request from "supertest"; import { app } from "../src/app";

describe("Content Security Policy", () => { it("should set CSP header", async () => { const response = await request(app).get("/");

expect(response.headers["content-security-policy"]).toBeDefined();
expect(response.headers["content-security-policy"]).toContain(
  "default-src 'self'"
);

});

it("should block inline scripts without nonce", async () => { const html = &#x3C;!DOCTYPE html> &#x3C;html> &#x3C;head> &#x3C;script>alert('blocked')&#x3C;/script> &#x3C;/head> &#x3C;/html> ;

// This would be blocked by CSP
// Verify in browser console or automated tests

});

it("should allow scripts with valid nonce", async () => { const response = await request(app).get("/");

// Extract nonce from response
const nonceMatch = response.text.match(/nonce="([^"]+)"/);
expect(nonceMatch).toBeDefined();

}); });

Common CSP Issues & Fixes

// Issue 1: Inline event handlers // ❌ Bad <button onclick="handleClick()">Click</button>

// ✅ Good <button id="myButton">Click</button> <script nonce="<%= cspNonce %>"> document.getElementById('myButton').addEventListener('click', handleClick); </script>

// Issue 2: Inline styles // ❌ Bad <div style="color: red;">Text</div>

// ✅ Good <style nonce="<%= cspNonce %>"> .red-text { color: red; } </style> <div class="red-text">Text</div>

// Issue 3: eval() usage // ❌ Bad eval('console.log("test")');

// ✅ Good // Don't use eval - refactor code

// Issue 4: Third-party scripts // ❌ Bad - no CSP entry <script src="https://cdn.example.com/script.js">&#x3C;/script>

// ✅ Good - whitelisted in CSP script-src: ['self', 'https://cdn.example.com']

Monitoring & Alerts

// monitoring/csp-violations.ts import { CloudWatch } from "@aws-sdk/client-cloudwatch";

const cloudwatch = new CloudWatch();

export async function trackCSPViolation(violation: { directive: string; blockedUri: string; userAgent: string; timestamp: Date; }) { await cloudwatch.putMetricData({ Namespace: "Security/CSP", MetricData: [ { MetricName: "Violations", Value: 1, Unit: "Count", Timestamp: violation.timestamp, Dimensions: [ { Name: "Directive", Value: violation.directive, }, { Name: "BlockedUri", Value: violation.blockedUri, }, ], }, ], });

// Alert if violations spike if (await isViolationSpike()) { await sendAlert({ title: "CSP Violation Spike Detected", message: High number of violations for ${violation.directive}, }); } }

Best Practices

  • Start report-only: Don't break production

  • Gradual rollout: 10% → 50% → 100%

  • Use nonces: Better than unsafe-inline

  • Monitor violations: Track and analyze

  • Test thoroughly: All pages and features

  • Document exceptions: Why resources whitelisted

  • Regular audits: Quarterly CSP review

Output Checklist

  • Security headers implemented

  • CSP policy defined (report-only)

  • CSP violation reporter endpoint

  • Nonce generation for inline scripts

  • Helmet.js configured

  • Rollout plan documented

  • Testing strategy implemented

  • Monitoring and alerts configured

  • Team trained on CSP

  • Staged rollout completed

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

responsive-design-system

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

rate-limiting-abuse-protection

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

bruno-collection-generator

No summary provided by upstream source.

Repository SourceNeeds Review