Introduction
What is XSS (in plain words)? XSS — Cross-Site Scripting — happens when a website lets someone put JavaScript into a page that other people view. That JavaScript runs in the visitor's browser and can do things like read data from the page, send that data to someone else, or change what the user sees. The website's server might not be directly damaged, but users can get hacked.
Why it matters (super short): An attacker can steal login tokens, show fake login forms, change account settings, or make the site look defaced. Even small sites can lose users' trust and get big problems from XSS.
Types of XSS (one-line each):
- Stored XSS: Attack code is saved on the site (e.g., in comments). Every visitor runs it.
- Reflected XSS: Attack code is sent in a URL or form and immediately shown back — usually when a user clicks a malicious link.
- DOM-based XSS: The client-side code (in the browser) takes input and inserts it into the page unsafely — the backend might never see it.
Quick real-world picture: Imagine someone writes a message on a public noticeboard (stored XSS). Everyone who reads the board reads the message (and its hidden instruction). That's how stored XSS spreads.
Intro Checklist (one-line):
- XSS = attacker-controlled script runs in other users' browsers → can steal or alter user data.
Detection
(How to find XSS in a site — easy steps, examples, and quick tests)
1. Start with simple manual tests (fast)
- Put a harmless test string into input fields:
<script>alert(1)</script>
or"><script>alert(1)</script>
and see if an alert pops up. - Try the same in comment forms, search boxes, profile fields, message fields, file names, and URL parameters.
Why this works: if the site echoes your input back into HTML without escaping/sanitizing, the browser will run the script.
2. Test reflected XSS (URL-based)
- Put payloads in query parameters, e.g.
?q=<script>alert(1)</script>
and open the URL. - Use common variants: with quotes, without quotes, inside HTML attributes (
onerror
,src
) because the payload may need a different shape depending on where input is inserted.
3. Test stored XSS (persistence)
- Submit a comment or profile text containing a test payload and then open the page as a different user or after logging out. If it executes on load, it's stored XSS.
4. DOM-based XSS tests (client-only)
- Look at client-side code that reads
location.hash
,location.search
,document.referrer
,innerHTML
, ordocument.write
. - Inject payloads into URL fragments (
#payload
) or parameters and see if the page modifies DOM unsafely.
5. Automated scanning tools (useful for large sites)
- Use scanners like OWASP ZAP, Burp Suite (community or pro features), or automated scripts to find reflected and some stored XSS.
- These tools can crawl pages and inject common payloads quickly.
6. Look for red flags in source & behavior
- Unsanitized use of
innerHTML
,outerHTML
,document.write()
, jQueryhtml()
,parseHTML()
, oreval()
in client code. - Server templates that directly include user text without escaping.
- Cookies without
HttpOnly
— suspicious but not proof of XSS.
7. Example payloads (non-destructive)
Use these lightweight checks during testing (don't harm production):
- Basic:
<script>alert('XSS')</script>
- Attribute:
"><img src=x onerror=alert('X')>
- DOM fragment:
#<svg/onload=alert(1)>
Always have permission before testing any site you do not own.
Detection Checklist (one-line):
- Test inputs & URLs with safe payloads, check stored places, inspect client code for unsafe DOM functions, and use scanners for broad coverage.
Prevention
(Simple practical steps — front-end, back-end, headers, and examples)
Front-end (browser-side) — immediately helpful
- Never insert raw user HTML.
- Use
textContent
instead ofinnerHTML
if you're adding plain text:
// safe:
element.textContent = userInput;
// unsafe:
element.innerHTML = userInput;
2. Sanitise HTML if you must allow HTML.
- Use a library like DOMPurify:
<script src="https://unpkg.com/dompurify@latest/dist/purify.min.js"></script>
<script>
const clean = DOMPurify.sanitize(dirtyInput);
element.innerHTML = clean; // now safer
</script>
3. Avoid risky APIs: document.write()
, eval()
, and innerHTML
on user content are dangerous.
4. Validate on client-side for usability only, but don't rely on it for security.
Back-end (server-side) — essential
- Validate input on the server: check types, lengths, and patterns (e.g., email regex). If it doesn't match, reject it.
- PHP example:
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
// reject
}
Escape output (HTML encode) before showing user input:
- PHP:
echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
- Node: use libraries like
html-entities
or template engine auto-escaping.
Sanitize stored HTML if your app stores HTML; run DOMPurify (server-side bindings exist) or a server-side sanitizer before saving.
HTTP headers & server config (strong defense)
Content-Security-Policy (CSP) — limit where scripts can come from:
Content-Security-Policy: default-src 'self'; script-src 'self'
CSP can block inline scripts and third-party script injection if configured properly.
X-Content-Type-Options: nosniff — prevents MIME-type sniffing.
Set cookies with HttpOnly
and Secure
so JavaScript cannot read sensitive cookies and they are sent only over HTTPS
Set-Cookie: session=abc; HttpOnly; Secure; SameSite=Strict
Serve over HTTPS everywhere — prevents man-in-the-middle attacks that could inject scripts.
Framework and tooling tips
- Use frameworks/templates that auto-escape user content (e.g., many server-side frameworks do this by default).
- Use a WAF (Web Application Firewall) to block obvious injection attempts at the edge.
- Perform security code reviews and include XSS checks in your CI pipeline.
Simple React-safe example
- Use JSX escaping and avoid
dangerouslySetInnerHTML
unless sanitized:
// safe: React escapes text automatically
<div>{userInput}</div>
// avoid: only use sanitized HTML with caution
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
CSP example (start simple, then harden)
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none';
Prevention Checklist (one-line):
- Validate input server-side, escape output, sanitize any HTML, avoid inserting raw user markup, use CSP + HttpOnly cookies + HTTPS, and test regularly.
Please comment on which part you like most. If you need any further assistance, please feel free to let me know!
"SECURING- DIGITAL ASSEST OF LIFE"
For more details, Ping a message on LinkedIn: