Skip to content
Back to skills

Dom Security Hardening

ASecurity

When hardening a web application against Cross-Site Scripting (XSS) and injection attacks.

  • 7 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added June 5, 2026
ai-agentsjavascriptrustgojavashellreactrefactoringapifrontendbackend

Works with

  • cursor
  • cli
  • api

Security analysis

A100/100

Scanned June 5, 2026

npx -y skills add KraitDev/skiLL.Md --skill dom-security-hardening --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dom Security Hardening?

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

Security grade badge for Dom Security Hardening
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kraitdev-dom-security-hardening/badge)](https://www.skillsdirectory.com/skills/kraitdev-dom-security-hardening)

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: dom-security-hardening
description: When hardening a web application against Cross-Site Scripting (XSS) and injection attacks.
version: 2.0.0
category: frontend
tags: [frontend, security, xss, csp]
skill_type: security
author: skiLLM
license: MIT
compatible_agents: [claude-code, cursor, copilot, codex]
estimated_context_tokens: 2200
dangerous: false
requires_review: true
security_level: dangerous
dependencies: [react-component-design]
triggers: [xss, injection, dom manipulation, csp, security, innerHTML, dangerouslySetInnerHTML]
permissions:
  filesystem: { read: true, write: true }
  network: { outbound: false }
  shell: { execute: false }
input_requirements: [HTML codebase, JavaScript with DOM manipulation]
output_contract: [no inline scripts, no inline styles, csp enforced, no unsafe dom apis]
failure_conditions: [required sanitizer library unavailable, csp cannot be enforced, legacy framework requires unsafe-inline]
last_updated: 2026-05-15
---

# DOM Security Hardening

## Purpose
XSS attacks kill applications. This skill hardens the DOM attack surface by enforcing a strict Content Security Policy, eliminating unsafe DOM APIs, and stripping execution vectors like inline scripts and styles. Following this skill is MANDATORY for any user-facing web application handling user input.

## When to use
- Setting up the initial `index.html` or document root of a web application
- Refactoring legacy code that relies on direct DOM manipulation
- Auditing a frontend codebase for XSS vulnerabilities
- Processing rich text or markdown input from untrusted users
- Creating forms or chat systems that accept user input

## When NOT to use
- CSS framework design (separate concern)
- React component prop validation (use React Component Design)
- Backend input validation (different layer, still required)

## Inputs required
- HTML document structure
- JavaScript files with DOM manipulation
- Understanding of Content Security Policy basics
- Sanitizer library decision (DOMPurify, sanitize-html, etc.)

## Workflow
1. **Enforce CSP**: Add strict `<meta http-equiv="Content-Security-Policy">` tag in HTML `<head>` (or HTTP headers)
2. **Externalize Assets**: Extract ALL inline `<script>` and `<style>` blocks into separate `.js` and `.css` files
3. **Remove Inline Events**: Replace inline `onclick="..."`, `onchange="..."` with standard `addEventListener` bindings
4. **Replace Unsafe DOM**: Replace `innerHTML`, `outerHTML`, `dangerouslySetInnerHTML` with `textContent` or `innerText`
5. **Implement Sanitizer**: If HTML rendering is REQUIRED, use DOMPurify or equivalent BEFORE insertion
6. **Test CSP**: Verify policy blocks all unauthorized execution attempts
7. **Verify No Bypasses**: Use security scanner (OWASP ZAP, Burp) to confirm XSS vectors are closed

## Rules
- MUST implement strict CSP: `default-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'`
- MUST NEVER use inline `<script>` blocks in HTML
- MUST NEVER use inline `style="..."` attributes
- MUST NEVER use `eval()`, `setTimeout(string)`, `new Function(string)`
- MUST NEVER use `innerHTML`, `outerHTML`, or `dangerouslySetInnerHTML` with user input
- MUST use `textContent` or `innerText` for all dynamic text insertions
- MUST sanitize user HTML with DOMPurify before any insertion
- MUST NOT use `'unsafe-inline'` or `'unsafe-eval'` in CSP

## Anti-patterns
- **`innerHTML` Assignment**: `element.innerHTML = userInput` (immediate XSS)
- **`javascript:` URIs**: `href="javascript:void(0)"` or `href="javascript:alert(1)"`
- **Unsafe CSP**: `Content-Security-Policy: default-src *; script-src 'unsafe-inline'`
- **Event Handler Strings**: Creating event handlers from user input or strings
- **Trusting User Input**: Assuming any user input is safe to insert into DOM
- **Missing Sanitizer**: Using rich text editor without sanitizing output

## Failure conditions
- CSP header/meta tag is missing
- Inline scripts or styles remain in production code
- `innerHTML` used with user input
- `dangerouslySetInnerHTML` used without sanitization
- CSP allows `'unsafe-inline'` or `'unsafe-eval'`
- Sanitizer library is not installed for rich text rendering

## Validation checklist
- [ ] CSP header/meta tag present with restrictive policy
- [ ] No `<script>` tags with inline code (all external)
- [ ] No inline `style="..."` attributes (all CSS classes)
- [ ] No `onclick`, `onchange`, `oninput` inline event handlers
- [ ] All DOM text insertions use `textContent` or `innerText`
- [ ] No `innerHTML`, `outerHTML`, or `dangerouslySetInnerHTML` with user input
- [ ] DOMPurify (or equivalent) used for any rich text rendering
- [ ] No `eval()`, `setTimeout(string)`, `new Function(string)` calls
- [ ] Security scanner passes (no XSS vulnerabilities detected)
- [ ] CSP blocks inline script execution (verify in browser console)

## Output format
- **HTML file**: Strict CSP meta tag in `<head>`, external `<script>` tags at end of `<body>`
- **JavaScript**: All DOM mutations via safe APIs (`textContent`, `className`, `setAttribute`)
- **CSS**: Separate `.css` files, no inline styles anywhere
- **Rich Text**: HTML sanitized via DOMPurify before insertion
- **Validation**: Automated XSS scan passes

## Security considerations
- **Threat Model**: Prevent XSS attacks via user input injection, DOM gadgets, third-party scripts
- **Mitigations**: CSP prevents execution, sanitizer prevents HTML injection, safe APIs prevent eval
- **Constraints**: CSP may conflict with analytics/ads (allow specific domains only)
- **Legacy Code**: Some frameworks may require CSP relaxation (document trade-offs)
- **Third-party Scripts**: Load analytics/ads only from trusted CDNs with subresource integrity (SRI)

## Agent execution notes
- Agent MAY: Add CSP header, externalize inline scripts/styles, replace innerHTML with textContent, implement DOMPurify
- Agent MUST NEVER: Use `'unsafe-inline'` or `'unsafe-eval'` in CSP, ignore sanitization requirements, leave inline event handlers
- Agent MUST ASK: Before adding third-party scripts, before relaxing CSP for legacy code, before using dangerouslySetInnerHTML
- Agent MUST VALIDATE: CSP policy is strict, no inline scripts remain, no unsafe DOM APIs, XSS scanner passes

## Example

**❌ Anti-pattern (Unsafe XSS vectors, no CSP):**
```html
<!-- No CSP -->
<a href="javascript:void(0)" onclick="submitForm()">Click me</a>
<div id="user-bio"></div>

<script>
  // Unsafe: direct user input to DOM
  document.getElementById('user-bio').innerHTML = getUserInput();
  
  // Unsafe: inline style
  document.getElementById('user-bio').setAttribute('style', 'color: red;');
  
  // Unsafe: event handler string
  setTimeout("console.log('vulnerable')", 1000);
</script>
```

**✅ Correct pattern (Hardened, safe):**
```html
<!-- Strict CSP enforced -->
<meta http-equiv="Content-Security-Policy"
  content="default-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'; img-src 'self' https:; font-src 'self';"
>

<a href="#" id="submit-btn">Click me</a>
<div id="user-bio"></div>

<!-- External script only -->
<script src="/js/app.js"></script>
```

```javascript
// app.js

// 1. Safe event binding
document.getElementById('submit-btn').addEventListener('click', (e) => {
  e.preventDefault();
  submitForm();
});

// 2. Safe text insertion (escapes HTML by default)
document.getElementById('user-bio').textContent = getUserInput();

// 3. Safe styling via CSS classes
document.getElementById('user-bio').classList.add('text-red');

// 4. If HTML rendering is absolutely required, sanitize first
import DOMPurify from 'dompurify';
document.getElementById('user-bio').innerHTML = DOMPurify.sanitize(getUserMarkdown());
```

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.