.diff-easy .badge { background: #0d3320; color: #3fb950; border: 1px solid #238636; } .diff-medium .badge { background: #3d2e00; color: #d29922; border: 1px solid #9e6a03; } .diff-hard .badge { background: #3d1114; color: #f85149; border: 1px solid #da3633; } .diff-expert .badge { background: #2a1541; color: #bc4dff; border: 1px solid #8b3dba; } .level-header h1 { font-size: 1.5rem; color: #e6edf3; margin-bottom: 0.5rem; } .defenses { font-size: 0.85rem; color: #8b949e; margin-bottom: 0.5rem; } .defenses strong { color: #c9d1d9; } .challenge-area { background: #161b22; border: 1px solid #30363d; border-radius: 12px; padding: 1.5rem; margin-bottom: 1.5rem; } form { display: flex; gap: 0.75rem; margin-bottom: 1rem; flex-wrap: wrap; } input[type="text"], textarea { flex: 1; min-width: 250px; padding: 0.6rem 1rem; background: #0d1117; border: 1px solid #30363d; border-radius: 8px; color: #c9d1d9; font-size: 0.9rem; font-family: inherit; } input[type="text"]:focus, textarea:focus { outline: none; border-color: #58a6ff; } button { padding: 0.6rem 1.5rem; background: #238636; border: 1px solid #2ea043; border-radius: 8px; color: #fff; font-size: 0.85rem; font-weight: 600; cursor: pointer; } button:hover { background: #2ea043; } .output { padding: 1rem; background: #0d1117; border: 1px solid #30363d; border-radius: 8px; min-height: 3rem; word-break: break-all; } .hint { margin-top: 1.5rem; } .hint details { background: #161b22; border: 1px solid #30363d; border-radius: 12px; padding: 1rem; } .hint summary { cursor: pointer; color: #d29922; font-weight: 600; font-size: 0.9rem; } .hint p { margin-top: 0.75rem; font-size: 0.85rem; color: #8b949e; line-height: 1.6; } .hint code { background: #21262d; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.8rem; color: #c9d1d9; } .writeup { display: none; margin-top: 1.5rem; background: linear-gradient(135deg, #161b22 0%, #1a1025 100%); border: 1px solid #8b3dba; border-radius: 12px; padding: 1.5rem; } .writeup h2 { font-size: 1.1rem; color: #c084fc; margin-bottom: 1rem; } .writeup h3 { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.05em; color: #bc4dff; margin-top: 1.25rem; margin-bottom: 0.5rem; } .writeup h3:first-of-type { margin-top: 0; } .writeup p { font-size: 0.85rem; color: #c9d1d9; line-height: 1.7; } .writeup code { background: #21262d; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.8rem; color: #e6edf3; } .success-banner { display: none; position: fixed; top: 0; left: 0; right: 0; padding: 1rem; background: linear-gradient(135deg, #238636, #2ea043); color: #fff; text-align: center; font-weight: 700; font-size: 1.1rem; z-index: 9999; animation: slideDown 0.3s ease; align-items: center; justify-content: center; gap: 1.5rem; } .success-banner a { color: #fff; background: rgba(255,255,255,0.2); padding: 0.35rem 1rem; border-radius: 6px; text-decoration: none; font-size: 0.85rem; font-weight: 600; border: 1px solid rgba(255,255,255,0.3); } .success-banner a:hover { background: rgba(255,255,255,0.3); } @keyframes slideDown { from { transform: translateY(-100%); } to { transform: translateY(0); } }
XSS Triggered! Level 29 Complete! Dashboard Next Level →
Level 29 — Expert

WebSocket XSS

Defenses: No HTTP parameters are used. The page connects to a WebSocket server and injects received messages directly into the DOM using innerHTML.

Welcome to the real-time chat demo. Messages are received instantly via WebSockets.

CONCEPT: WebSockets and DOM XSS

Modern applications often use WebSockets for real-time bidirectional communication. A common mistake is trusting the data coming from the WebSocket server just because it's not a direct HTTP response. If the client-side JavaScript receives a WebSocket message and places it directly into the DOM without sanitization (e.g., using innerHTML instead of textContent), it creates a DOM-based XSS vulnerability. This is especially dangerous in chat apps where an payload sent by one user will be broadcast to and executed on every other connected user's browser.

Live Chat

[System] Connecting to chat server...

Note: There is no input field provided on this page. You must interact with the WebSocket directly via your browser's Developer Tools Console.

Hint (try on your own first!)

Why It Worked

Key Lesson

Real-World Application