Back to Articles

Electric Scan: Why Electron Might Be the Right Choice for Web Reconnaissance

[ View on GitHub ]

Electric Scan: Why Electron Might Be the Right Choice for Web Reconnaissance

Hook

Most security tools chase performance by stripping down browsers, but Electric Scan does the opposite—it embraces Electron's bloat to solve a detection problem that lightweight alternatives can't.

Context

Web reconnaissance has always involved a fundamental tradeoff: speed versus accuracy. When penetration testers and security researchers scan hundreds or thousands of web services, they need screenshots to quickly identify interesting targets—login panels, admin interfaces, unusual applications. Early tools like wkhtmltoimage used WebKit to render pages, but they struggled with modern JavaScript-heavy applications. Python-based tools like EyeWitness improved the situation by using Selenium with full browsers, but single-threaded execution made large scans painfully slow.

The Go renaissance brought us tools like GoWitness and Aquatone—blazing fast, tiny binaries that could screenshot thousands of targets in minutes. But there's a catch: headless Chrome and Firefox leave fingerprints. Websites can detect headless browsers through dozens of JavaScript properties, canvas fingerprinting, and behavioral analysis. For security research, getting blocked or served a fake page defeats the entire purpose. Electric Scan takes a contrarian approach: instead of optimizing for lightness, it leverages Electron's full desktop Chrome experience, complete with GUI, to render pages exactly as users see them while parallelizing the work across multiple processes.

Technical Insight

Electron Processes

URLs + Options

Spawn Workers

Create Isolated

Create Isolated

Create Isolated

Configure

Configure

Configure

Fetch Page

Fetch Page

Fetch Page

PNG Buffer

PNG Buffer

PNG Buffer

Categorize

Labeled Screenshots

CLI Entry Point

Screenshot Manager

Worker Pool

Renderer 1

BrowserWindow

Renderer 2

BrowserWindow

Renderer N

BrowserWindow

Proxy Handler

SOCKS/HTTP/HTTPS

ML Classifier

EyeWitness

Screenshot Storage

PNG Files

System architecture — auto-generated

Electric Scan's architecture reveals thoughtful decisions about where to spend complexity budget. At its core, it spawns multiple Electron renderer processes—each essentially a full Chrome instance—that can capture screenshots in parallel. This multi-process model is implemented using Electron's BrowserWindow API with careful isolation.

Here's how a typical screenshot capture flow works:

import { BrowserWindow } from 'electron';

async function captureScreenshot(url: string, timeout: number = 30000) {
  const window = new BrowserWindow({
    width: 1920,
    height: 1080,
    show: false, // Hidden but not headless
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      sandbox: true
    }
  });

  try {
    await window.loadURL(url, { timeout });
    // Wait for network idle
    await new Promise(resolve => setTimeout(resolve, 2000));
    const image = await window.capturePage();
    return image.toPNG();
  } finally {
    window.destroy();
  }
}

The key insight is the show: false option. Unlike headless mode, this creates a real browser window that's simply hidden from view. The JavaScript environment sees all the properties of a normal desktop browser—navigator.webdriver is undefined, Chrome's DevTools Protocol fingerprints are absent, and canvas fingerprinting matches real users. This is Electron working as intended: the same Chromium that renders VS Code and Slack is rendering your targets.

The security-conscious design is equally important. Electric Scan follows Electron's security best practices by disabling Node.js integration in renderer processes and enabling context isolation. This matters because screenshot tools navigate to untrusted URLs—potentially malicious web applications controlled by adversaries. With nodeIntegration: false, even if an attacker achieves XSS in a captured page, they can't access Node.js APIs or the filesystem. The main process handles all privileged operations through carefully validated IPC channels.

Proxy support is implemented at the Chromium session level rather than system-wide, giving fine-grained control:

const session = window.webContents.session;
await session.setProxy({
  proxyRules: 'socks5://127.0.0.1:9050', // Tor example
  proxyBypassRules: '<local>'
});

This enables scenarios like routing reconnaissance through Tor or corporate proxies without affecting other applications. Each BrowserWindow can have its own session with different proxy settings, enabling parallel scans through different exit points.

The machine learning classifier integration from EyeWitness adds automatic categorization. After capturing screenshots, Electric Scan runs them through a trained model that identifies common patterns—login pages, default Apache installations, Jenkins servers, router admin panels. This transforms a folder of screenshots into a prioritized target list. While the ML model isn't custom-trained for Electric Scan, it benefits from EyeWitness's years of community-contributed signatures.

The tradeoff is resource consumption. Each Electron renderer process consumes 100-300MB of RAM. Scanning 100 targets with 5 parallel workers means 500MB-1.5GB minimum. Compare this to GoWitness, which uses 50-100MB total for the same job. But that memory buys you rendering accuracy that's impossible to achieve with stripped-down alternatives.

Gotcha

Electric Scan's Achilles heel is scale. While the multi-process architecture enables parallelism, each process is a full Chrome instance. Memory usage scales linearly with parallel workers—run 10 workers and you're easily consuming 2-3GB of RAM. For organizations scanning thousands of assets continuously, this becomes prohibitive. The tool shines for focused reconnaissance of dozens to low hundreds of targets, but it's not designed for the "scan the entire IPv4 space" use case.

The second limitation is community momentum. With 68 GitHub stars and development primarily by a single author, you're not getting the rapid iteration and extensive plugin ecosystem of more popular alternatives. Bug fixes depend on a small contributor base, and feature requests may go unaddressed. The ML classifier is borrowed from EyeWitness rather than actively maintained within the project, so improvements to categorization accuracy require upstream changes. If you encounter an edge case or need custom modifications, you'll likely be maintaining a fork rather than finding community solutions.

Verdict

Use if: You're doing targeted penetration testing or red team reconnaissance where rendering accuracy matters more than speed, you need to avoid headless browser detection, you value a cross-platform GUI for interactive workflows, or you're already comfortable with TypeScript/Electron and want to extend the tool. The security-conscious architecture makes it trustworthy for navigating to hostile targets. Skip if: You're scanning thousands of assets where resource efficiency is critical, you need active community support and frequent updates, you prefer battle-tested CLI tools with extensive documentation, or you're running on memory-constrained systems. For large-scale continuous monitoring, GoWitness or Aquatone will serve you better despite their detection tradeoffs.

// ADD TO YOUR README
[![Featured on Starlog](https://starlog.is/api/badge/developer-tools/moloch-electric-scan.svg)](https://starlog.is/api/badge-click/developer-tools/moloch-electric-scan)