⚠️ EDUCATIONAL DEMO: Demonstrates XSS attack enabled by missing Content Security Policy. The XSS runs in a sandboxed simulation — no real scripts are injected.

Content Security Policy Missing — XSS Demo

Without a Content-Security-Policy header, any injected script executes freely. One vulnerable comment field is all it takes.

THE SECURITY RISK IN PLAIN ENGLISH

XSS (Cross-Site Scripting) means an attacker gets their JavaScript to run on your page. This can happen through comment fields, search boxes, URL parameters, or any input that gets reflected back into the page.

Without CSP, the browser has no way to know which scripts are legitimate and which were injected by an attacker. It runs all of them. With CSP, the server tells the browser: "Only run scripts I explicitly approve." An injected <script> tag or onerror handler is blocked before it executes.

Try it: Type an XSS payload into the comment field below. Toggle between no-CSP and CSP modes to see the difference.

⬇ MOCK SCHOOL PORTAL — COMMENT FIELD
✕ No CSP Header
✕ Content-Security-Policy: (missing)

Announcements

Teacher Reyes
Reminder: Science project due Friday.
Principal Santos
School photos on March 25. Please wear uniform.
Try: <img src=x onerror=stealCookies()> <script>stealCookies()</script> Hello world

❌ Current State (No CSP)

  • No Content-Security-Policy header returned
  • Any reflected/stored XSS payload executes immediately
  • Attacker can steal session cookies, redirect to phishing page, keylog passwords
  • One vulnerable comment field compromises every visitor to that page
  • Browser has no mechanism to distinguish legitimate from injected scripts

✅ Fix (CSP Header)

  • Nginx: add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;
  • Apache: Header always set Content-Security-Policy "default-src 'self'"
  • Start with Content-Security-Policy-Report-Only to audit before enforcing
  • Move inline scripts to external .js files — inline scripts require 'unsafe-inline' which weakens CSP
  • Also use frame-ancestors 'self' to prevent clickjacking (replaces X-Frame-Options)

⚠️ XSS Executed!

stealCookies() was called. In a real attack this function would:

Every student and teacher who loads this page would be affected — not just the person who submitted the comment.