The Most Advanced Web Worker Security Scanner
███████╗ █████╗ ██████╗ ██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗██████╗
██╔══██╗██╔══██╗██╔══██╗ ██║ ██║██╔═══██╗██╔══██╗██║ ██╔╝██╔════╝██╔══██╗
██████╔╝███████║██║ ██║ ██║ █╗ ██║██║ ██║██████╔╝█████╔╝ █████╗ ██████╔╝
██╔══██╗██╔══██║██║ ██║ ██║███╗██║██║ ██║██╔══██╗██╔═██╗ ██╔══╝ ██╔══██╗
██████╔╝██║ ██║██████╔╝ ╚███╔███╔╝╚██████╔╝██║ ██║██║ ██╗███████╗██║ ██║
╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
⚠️ FOR AUTHORIZED SECURITY TESTING ONLY — Use solely against targets for which you have explicit written permission.
- Overview
- Architecture
- Scan Pipeline
- Detection Engine
- Vulnerability Catalog
- Scoring System
- Output Artifacts
- Installation
- Usage
- CLI Reference
- Output Examples
- Changelog
- Legal Disclaimer
BadWorker is a Node.js security scanner purpose-built to identify vulnerabilities in web applications that leverage the Web Workers API. It goes beyond passive network inspection by instrumenting browser APIs at runtime via Puppeteer, capturing worker code at the moment of instantiation — including ephemeral blob-URL workers that vanish immediately after creation.
Web Workers run in isolated threads with access to fetch, importScripts, and postMessage — making them a high-value attack surface that is routinely missed by conventional scanners. Vulnerabilities such as dynamic importScripts injection or missing postMessage origin validation can lead to full remote code execution within the worker's security context.
| Capability | Standard Scanner | BadWorker v3.0 |
|---|---|---|
| Runtime worker detection | ✅ | ✅ |
| Blob worker capture | ❌ | ✅ NEW |
| Static bundle analysis | ❌ | ✅ NEW |
| Latent threat detection | ❌ | ✅ NEW |
| CRITICAL severity tier | ❌ | ✅ NEW |
| Nuclei template generation | ❌ | ✅ NEW |
| HTML executive report | ❌ | ✅ NEW |
| Automatic PoC classification | ❌ | ✅ NEW |
bad-worker.js
│
├── class BadWorker
│ │
│ ├── constructor(url, options) — Config, result schema init
│ │
│ ├── scan() — Top-level orchestrator
│ │ ├── phase1_detection()
│ │ ├── phase2_staticAnalysis()
│ │ ├── phase3_analysis()
│ │ └── phase4_reporting()
│ │
│ ├── Detection Subsystem
│ │ ├── evaluateOnNewDocument() — Browser API hooks injection
│ │ ├── identifyBundles() — JS bundle fingerprinting
│ │ └── [Request Interception] — Network-level script capture
│ │
│ ├── Analysis Subsystem
│ │ ├── analyzeWorkerCode() — Per-worker vuln scanning
│ │ ├── findLatentWorkers() — Static pattern matching
│ │ ├── extractWorkersFromBundle()— Bundle-embedded worker extraction
│ │ └── calculateSecurityScore() — Risk scoring engine
│ │
│ └── Reporting Subsystem
│ ├── generateDetailedJSON() — Machine-readable full report
│ ├── generateStandardReport() — report.json
│ ├── generateHTMLReport() — Interactive visual report
│ ├── generateNucleiTemplates() — Ready-to-run Nuclei YAML
│ └── generateSummary() — Executive summary TXT
│
└── CLI — Argument parser + entry point
BadWorker executes four sequential phases:
Puppeteer launches a Chromium instance with security isolation flags disabled (--disable-web-security, --disable-features=IsolateOrigins) to maximize detection coverage. Before navigation, the following hooks are injected into the page via evaluateOnNewDocument:
Blob Hook (window.Blob)
Intercepts every Blob constructor call. When the blob content contains worker-indicative strings (self., postMessage, onmessage, importScripts), the code is captured in memory and tagged with a random blobId.
URL Hook (window.URL.createObjectURL)
Intercepts blob URL creation. When a tagged blob is converted to a URL, its captured code is stored in window.__BLOB_WORKERS__ keyed by URL — preserving the source code before the URL is consumed.
Worker Hook (window.Worker)
Intercepts every new Worker() call. Records the worker URL, creation timestamp, type (regular, blob, data-URL), and — for blob workers — attaches the pre-captured source code from __BLOB_WORKERS__.
Service Worker Hook (navigator.serviceWorker.register)
Tracks all service worker registration calls with URL and options.
Shared Worker Hook (window.SharedWorker)
Tracks SharedWorker instantiation.
After navigation and a configurable wait period (--wait), all captured data is extracted from the page context.
After runtime detection, BadWorker downloads all JavaScript bundles identified during Phase 1. Each bundle is analyzed for:
- Latent worker patterns —
importScripts,eval,new Function,new Workerfound in code not yet executed at page load. - Embedded worker code — Workers serialized as strings within the bundle (a common bundler output pattern), extracted via regex heuristics and saved as individual
.jsfiles for analysis.
All collected workers — active (runtime-detected), blob (captured inline), and extracted (from bundles) — are passed through analyzeWorkerCode(). Latent threats are processed separately with reduced CVSS scores since exploitation requires triggering the dormant code path.
CRITICAL Escalation Logic (v3.0) When a HIGH severity vulnerability is found within an active worker context (runtime-detected or blob-captured), it is automatically promoted to CRITICAL with a CVSS bump of +2.0 (capped at 10.0), reflecting that the vulnerable code is confirmed running in the page.
All artifacts are serialized to the output directory.
| Hook | Target | Purpose |
|---|---|---|
window.Blob |
Blob constructor | Capture inline worker source code |
window.URL.createObjectURL |
URL factory | Map blob URLs to captured source |
window.Worker |
Worker constructor | Detect regular + blob workers |
navigator.serviceWorker.register |
SW registration | Track service workers |
window.SharedWorker |
SharedWorker constructor | Track shared workers |
| Pattern | Regex | Severity |
|---|---|---|
Dynamic importScripts |
/importScripts\s*\(\s*([^)]+)\s*\)/g with dynamic param check |
HIGH |
eval usage |
/\beval\s*\(/g |
HIGH |
Function constructor |
/new\s+Function\s*\(/g |
HIGH |
| Worker creation code | /new\s+Worker\s*\(\s*([^)]+)\s*\)/g |
INFO |
| Embedded worker patterns | Multi-pattern regex (3 heuristics) | Varies |
BadWorker detects five vulnerability classes out of the box:
- Severity: HIGH → CRITICAL (when active)
- CVSS: 7.5 (base) / 9.5 (critical)
- Description: Worker accepts an arbitrary URL via
postMessageand passes it directly toimportScripts()with no whitelist validation. - Impact: Arbitrary code execution within the worker thread, data exfiltration, integrity compromise.
- OWASP: A03:2021 – Injection
- PoC Generated: Yes
- Detection: Pattern
/importScripts\s*\(\s*[\w.]+\s*\)/with absence of validation guards (includes,startsWith,match,===,WHITELIST,TRUSTED). - Remediation: Implement a URL allowlist. Only permit scripts from explicitly trusted CDN domains.
- Severity: MEDIUM
- CVSS: 5.3
- Description: Worker calls
self.postMessage()but noevent.originore.origincheck is present in the message handler. - Impact: Cross-origin data leakage; XSS escalation in the worker security context.
- OWASP: A01:2021 – Broken Access Control
- PoC Generated: No
- Detection: Count of
self.postMessage> 0 and count ofe.origin|event.origin=== 0. - Remediation: Validate
event.originin everyonmessagehandler before processing data.
- Severity: HIGH → CRITICAL (when active)
- CVSS: 8.1 (base) / 10.0 (critical)
- Description: Worker code uses
eval()ornew Function()— classic code injection primitives. - Impact: Remote code execution.
- OWASP: A03:2021 – Injection
- PoC Generated: Yes
- Remediation: Replace
eval/FunctionwithJSON.parse()or structured data handling. Never interpret user input as code.
- Severity: LOW
- CVSS: 3.7
- Description:
JSON.parse()called without a surroundingtry/catch, making the worker susceptible to crash on malformed input. - Impact: Denial of Service (worker thread crash).
- OWASP: A04:2021 – Insecure Design
- PoC Generated: No
- Detection: Presence of
JSON.parse(without a matchingtry { ... JSON.parse ... } catchblock. - Remediation: Wrap all
JSON.parse()calls in try-catch.
- Severity: MEDIUM
- CVSS: 6.5
- Description: Worker constructs
fetch()URLs using string concatenation, allowing an attacker to influence the destination. - Impact: Server-Side Request Forgery (SSRF), internal network scanning.
- OWASP: A10:2021 – Server-Side Request Forgery
- PoC Generated: No
- Detection: Pattern
/fetch\s*\([^)]*\+[^)]*\)/. - Remediation: Validate and sanitize all URLs before issuing fetch requests. Use an allowlist of permitted origins.
BadWorker computes a Security Score (0–100) by starting at 100 and applying deductions:
| Finding | Deduction |
|---|---|
| CRITICAL vulnerability | −40 pts each |
| Active HIGH vulnerability | −30 pts each |
| Active MEDIUM vulnerability | −15 pts each |
| Active LOW vulnerability | −5 pts each |
| Latent HIGH vulnerability | −10 pts each |
Risk Level is derived from the resulting score:
| Condition | Risk Level |
|---|---|
| Any CRITICAL vulnerability | CRITICAL |
| Any active HIGH vulnerability | HIGH |
| Latent HIGH > 2 or active MEDIUM > 2 | HIGH |
| Latent HIGH > 0 or active MEDIUM > 0 or active LOW > 3 | MEDIUM |
| None of the above | LOW |
All files are written to the output directory (default: ./bad-worker-enterprise):
bad-worker-enterprise/
├── detailed.json — Full machine-readable report (Nuclei/Metasploit compatible)
├── report.json — Standard summary report
├── report.html — Interactive visual executive report
├── summary.txt — Plain-text executive summary
│
├── blob-workers/
│ └── blob-worker-<timestamp>-<id>.js — Captured blob worker source files
│
├── extracted/
│ └── worker_pattern<N>_<id>_<bundle>.js — Workers extracted from bundles
│
├── bundles/
│ └── <filename>.js — Downloaded JS bundles
│
└── nuclei/
└── <hostname>-<vuln-id>.yaml — Nuclei templates for exploitable vulns
{
"metadata": { "tool", "version", "scan_type", "scan_mode", "target", "timestamp", "duration_seconds" },
"target_info": { "url", "workers_active", "workers_latent", "service_workers", "javascript_sources", "bundles_analyzed" },
"security_assessment": {
"overall_score": 0,
"risk_level": "CRITICAL|HIGH|MEDIUM|LOW",
"total_vulnerabilities": 0,
"breakdown": { "active": { "critical", "high", "medium", "low" }, "latent": { "high", "medium", "low" } }
},
"vulnerabilities": { "active": [...], "latent": [...] },
"workers": { "active": [...], "latent": [...] },
"extracted_workers": [...],
"remediation": [{ "vulnerability", "recommendation", "priority", "status" }]
}For every HIGH/CRITICAL exploitable vulnerability, a Nuclei YAML template is generated with the target URL, CWE ID, severity, and CVSS score pre-populated — ready for immediate use with nuclei -t <file>.
Prerequisites: Node.js ≥ 18, npm
# Clone or place bad-worker.js in your working directory
npm install puppeteer
# Make executable (optional)
chmod +x bad-worker.jsPuppeteer will automatically download a compatible Chromium binary on first install.
node bad-worker.js https://target.example.comSome applications initialize workers only after user interaction or after a delay. Increase the wait time:
node bad-worker.js https://target.example.com --wait 15000Useful for debugging or verifying that interactions are triggering workers correctly:
node bad-worker.js https://target.example.com --deep-scan --no-headlessnode bad-worker.js https://target.example.com --no-staticnode bad-worker.js https://target.example.com --output ./reports/myapp-$(date +%Y%m%d)USAGE:
node bad-worker.js <url> [options]
ARGUMENTS:
<url> Target URL (required)
OPTIONS:
--timeout <ms> Page load timeout in milliseconds [default: 30000]
--wait <ms> Worker initialization wait time [default: 10000]
--output <dir> Output directory for all artifacts [default: ./bad-worker-enterprise]
--no-download Skip automatic JS bundle download
--no-headless Run Chromium in visible (GUI) mode
--deep-scan Enable deep scanning mode
--no-static Disable static bundle analysis
--verbose, -v Enable verbose output (print each script URL)
--help, -h Show help and exit
[14:32:01] 🔥 ENTERPRISE SCAN COMPLETE 🔥
[14:32:01] ⏱️ Duration: 23s
[14:32:01] 👷 Active Workers: 2
[14:32:01] Blob Workers Captured: 1
[14:32:01] 👻 Latent Workers: 4
[14:32:01] 💻 Code Extracted: 1
[14:32:01] 🔴 Total Vulnerabilities: 5
[14:32:01] 💀 CRITICAL: 1
[14:32:01] 🔥 HIGH (Active): 1
[14:32:01] ⚠️ MEDIUM (Active): 2
[14:32:01] ℹ️ LOW (Active): 1
[14:32:01] 🛡️ Security Score: 15/100
[14:32:01] ⚠️ Risk Level: CRITICAL
The generated report.html includes:
- Color-coded security score badge (green ≥ 80, orange ≥ 50, red < 50)
- Statistics dashboard (active workers, latent workers, total sources, vulnerabilities by tier)
- Sortable vulnerability table with ACTIVE / LATENT badges
- Source file and line number references for each finding
- NEW: Blob worker capture via
window.Blob+URL.createObjectURLhooks - NEW: CRITICAL severity tier (HIGH in active context = CRITICAL)
- NEW: Static bundle analysis with latent threat detection
- NEW: Worker extraction from bundle-embedded strings (3 regex heuristics)
- NEW: Nuclei template auto-generation for exploitable vulns
- NEW: Multi-format reporting: JSON, HTML, TXT
- IMPROVED: Default wait time increased from 5 s to 10 s
- IMPROVED: Output directory renamed to
./bad-worker-enterprise - IMPROVED: Better false-positive reduction in pattern matching
- Static analysis of bundles (no active workers required)
- Latent threat detection
- Generic pattern matching
- Improved reporting
BadWorker is designed for authorized penetration testing, bug bounty research, and security audits only. Running this tool against systems without explicit written authorization from the system owner may violate the Computer Fraud and Abuse Act (CFAA), Brazil's LGPD/Lei 12.737 (Lei Carolina Dieckmann), and equivalent laws in other jurisdictions.
The authors assume no liability for misuse. Always obtain written scope authorization before scanning.