# Ghost Browser Connect MCP clients such as Codex and Claude Code to the browser with the [MCP setup guide](docs/mcp.md). A real Chromium, driven by numbered annotations instead of CSS selectors, behind an HTTP API — with an autonomous, multi-layer AI security reconnaissance & vulnerability auditing engine. ## Why it looks like this The trick it is built on is **Set-of-Mark**: before any decision, every interactive element on screen gets a numbered box painted over it *in the live DOM*, the page is screenshotted, the boxes are stripped off again, and the caller gets the annotated picture plus a numbered list. You then say `click 3`. That is the whole reason this works where selector-based automation does not. A selector breaks when the site is redesigned; a numbered screenshot is redrawn from whatever is on screen right now. And a language model is far better at looking at a picture than at parsing a DOM tree. `src/inspector.js` is the marking code, lifted unchanged from the agent platform where it has been running in production. ## What is here, and what is not Built: sessions with real limits, Set-of-Mark analysis, navigate/click/type/read, an SSRF guard, key auth with per-plan concurrency, and a console to drive it by hand. Not built yet, by design: the AI navigation loop, the recipe compiler, and billing. Each is easier against a service that already survives concurrency, which is what this phase is for. ## The limits are the product A browser session is not a request — it is a live process holding memory for its whole life. One Chromium per pod with a **context** per session (isolated cookies and storage, shared process) is the difference between roughly two sessions per pod and ten. | Limit | Default | Env | |---|---|---| | Sessions per pod | 8 | `MAX_CONTEXTS` | | Idle before close | 5 min | `IDLE_MS` | | Absolute session TTL | 2 h | `SESSION_TTL_MS` | | Drain at memory | 80% | `MEMORY_LIMIT_PCT` | These are starting points from the plan, not measurements. Watch `/v1/capacity` under a real workload and move them. Memory is read from the **cgroup**, not from the host: in Kubernetes a 4 GB pod on a 64 GB node would otherwise look like it had endless headroom right up until it was killed. When the ceiling is crossed the pod stops accepting sessions, finishes what it has, and exits so it is replaced — on our terms rather than the OOM killer's. ## The guard `src/guard.js` is the most important file here. A browser anyone can point at any URL is a server-side request forgery engine, and this one runs *inside* the cluster it would be attacking — the metadata endpoint, the Kubernetes API, another tenant's service are all just URLs from in here. Two bypasses it specifically closes: a public hostname that **resolves** to a private address (so names are resolved and every returned address is checked), and a public URL that **redirects** to one (so the landing URL is re-checked after navigation, and the page is blanked if it moved somewhere it should not). ## API ``` POST /v1/sessions → { sessionId, expiresAt, plan } POST /v1/sessions/:id/navigate { url } GET /v1/sessions/:id/analyze → { elements, summary, screenshot } POST /v1/sessions/:id/click { index } | { text } POST /v1/sessions/:id/type { index, text, submit } GET /v1/sessions/:id/content → cleaned page text GET /v1/sessions/:id/screenshot → image/jpeg DELETE /v1/sessions/:id GET /v1/capacity → open; what this worker can still take GET /v1/config → open; what is configured, never a secret ``` Auth is `Authorization: Bearer `. Keys come from `API_KEYS` as `key:plan,key:plan` or JSON. There is no plan that opens a browser without a key: a session costs real memory for its whole life, so an anonymous one is a way to spend someone else's money. ## Running it ``` API_KEYS=somekey:solo npm start ``` Its own image, because the platform's shared runner has no browser and installing one at container start would mean a 300 MB download on every pod restart. The Dockerfile's Playwright tag must track the `playwright` version in `package.json` — they are one thing. ## 🛡️ Autonomous Security Reconnaissance & Audit Engine Ghost Browser includes a fully autonomous, production-grade security auditing and reconnaissance suite built directly on top of its live browser runtime. Unlike traditional CLI scanners that blindly flood endpoints with raw HTTP requests, Ghost Browser navigates web apps like a senior security researcher: rendering client-side JavaScript (SPAs), monitoring DOM mutations, evaluating network telemetry, and mathematically proving exploitability without breaking production services. ### 4-Layer Autonomous Audit Workflow ``` [Target URL] │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Layer 1: Passive Recon & Asset Discovery │ │ • DNS Hygiene (SPF, DMARC, CAA, Wildcard Detection) │ │ • Subdomain Enumeration via Certificate Transparency (CT) │ │ • TLS Handshake, Protocol & Cipher Audit │ └────────────────────────────┬────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Layer 2: Perimeter & Service Inspection │ │ • Non-destructive TCP Banner Grabbing (SSH, Databases, etc) │ │ • Service Daemon & CVE Correlation │ │ • HTTP Defensive Headers & WAF Identification │ └────────────────────────────┬────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Layer 3: Application Logic & DAST Probes │ │ • Benign Canary DOM Taint & Safe Reflection Analysis (XSS) │ │ • Broken Access Control & BOLA/IDOR Matrix Auditing │ │ • Statistical Timing-Differential SQLi Probing │ │ • Polyglot Server-Side Template Injection (SSTI) │ │ • Sensitive Path & Configuration Discovery (SPA-Aware) │ └────────────────────────────┬────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Layer 4: Turnkey Remediation & Dual-Scorecard Reporting │ │ • Dual Scorecard: Posture Hardening vs Active Exploitation │ │ • Reproducible curl PoC commands for every finding │ │ • Pull-Request Ready Code Diffs for Instant Remediation │ │ • Compliance Mapping (SOC 2 Type II, ISO 27001, PCI-DSS) │ └─────────────────────────────────────────────────────────────┘ ``` ### Key Capabilities - **SPA-Aware Reconnaissance**: Modern web applications render content client-side via React, Vue, or Next.js. Ghost Browser captures DOM events, extracts dynamically loaded backend routes (`/api/*`, `/v1/*`), and discriminates real files from SPA soft-404 redirects. - **Zero-False-Positive Canary Reflection**: Tests user input reflection in DOM sinks (`innerHTML`, `outerHTML`, `document.write`) using safe, unique mathematical boundaries (`__gbcanary_...`) to definitively prove whether user inputs are sanitized or vulnerable to cross-site scripting (CWE-79). - **Wildcard DNS & Subdomain Isolation**: Automatically detects wildcard DNS records (`*.domain.com`) to prevent dictionary hallucinations. Subdomain discovery intersects with live Certificate Transparency (crt.sh) logs and TLS Subject Alternative Names (SANs) for 100% verified asset enumeration. - **Dual-Scorecard Architecture**: - **Infrastructure & Defensive Posture**: Evaluates defense-in-depth gaps (missing CSP, HSTS, XFO, DMARC). These are clearly labeled as hardening recommendations — never conflated with critical exploits. - **Application Logic & Exploitability**: Evaluates verified vulnerabilities (BOLA/IDOR, SQLi, SSRF, RCE, broken auth). When no active exploits succeed, targets achieve a **100/100 Grade A+ (Clean)** rating. - **Turnkey Remediation**: Every single advisory automatically generates an exact, non-destructive `curl` reproduction command and a ready-to-merge configuration or middleware code patch. --- ## 🏔️ The AppSec & Red Team Iceberg Ghost Browser is designed to bridge the gap between simple vulnerability scanners and elite red team operations. Below is our security architecture iceberg — displaying what is already fully implemented, battle-tested, and validated, alongside the open-source frontier we are actively building with the community. ``` THE APPSEC & RED TEAM ICEBERG ▲ / \ / \ [WHAT WE HAVE IMPLEMENTED & VALIDATED] / \ / • \ • Autonomous Perimeter, DNS & Wildcard Isolation (gb_recon) / • \ • Subdomain Discovery via CT Logs & TLS SANs (crt.sh) / • \• Burp-Style HTTP Verb, CORS & Header Tampering / • \• Semantic SPA Route & Dynamic API Discovery / • \• Zero-False-Positive Canary DOM Taint & XSS Proof / • \• Unauthenticated Mutation & BOLA/IDOR Matrix (authMatrix) / • \• Dual-Session Cross-Tenant Privilege Escalation / • \• JWT Hygiene, Exp Claims & Algorithm Confusion / • \• JWT Key Confusion (RSA to HMAC HS256 Downgrade) / • \• RFC 6585 Throttling, Concurrency & TOCTOU Race Testing / • \• GraphQL Introspection, Depth & Batching DoS Probes / • \• OAST Ephemeral Canary Blind SSRF & Callbacks / • \• Cloud Metadata SSRF & Token Traversal (IMDSv2/K8s) / • \• Statistical Timing-Differential SQLi (sqliTiming) / • \• Multi-Step Second-Order Stored Injection / • \• Polyglot Server-Side Template Injection (SSTI) / • \• Client-Side Prototype Pollution & Gadgets / • \• HTTP Request Smuggling & Cache Poisoning / • \• Cross-Site WebSocket Hijacking (CSWSH) / • \• OAuth 2.0 PKCE & Redirect Boundary Auditing / • \• Business Logic & Price Tampering (businessLogicAuditor) / • \• Subdomain Takeover & Dangling Cloud Buckets / • \• Non-Destructive 3-Pillar CVE Verification / • \• Deep Inter-File AST Symbol Resolution / • \• Photographic Visual Proof (gb_capture_proof) / • \• SOC 2 / ISO 27001 Compliance Auto-Mapping ~~~~~~/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ (Waterline) / \ / [WHAT'S BELOW THE SURFACE] \ ◄── THE NEXT-GEN FRONTIER / \ (CONTRIBUTIONS WELCOME!) / [ ] 1. Stateful WebSocket Binary Frame Fuzzing (CWE-1385) \ / [x] 2. Business Logic Pricing, Cart & Currency Race Tampering \ (COMPLETED & VALIDATED!) / [ ] 3. AI Agent Prompt Injection & Tool Jailbreaks (OWASP LLM01) \ / [ ] 4. WebAuthn, FIDO2 & Passkey Attestation Bypass Probes \ \ [ ] 5. SAML 2.0 XML Signature Wrapping (XSW) & Entity Expansion / \ [ ] 6. eBPF-Powered Kernel-Level Network & Memory Taint Tracing / \ [ ] 7. Mobile App Deep Link & Intent Scheme Injection Fuzzing / \ [ ] 8. Dynamic Multi-Step WAF Bypass & Obfuscation Mutation / \ [ ] 9. GraphQL WebSocket Subscription Injection & Stream DoS / \[ ] 10. HTTP/2 & gRPC Multiplexing Desync & Stream Reset Flooding / \________________________________________________________________/ ``` ### 🚢 Above the Surface: Validated & Live in Ghost Browser The top of the iceberg represents our core autonomous DAST and perimeter suite, running with zero dependencies and production-safe guards: | Category | Validated Capability | Core Engine / Module | |---|---|---| | **Perimeter & DNS** | Wildcard DNS isolation, SPF/DMARC/CAA hygiene, CT-log subdomain harvesting | `perimeter.js`, `subdomainDiscovery.js` | | **Transport & SSL** | TLS cipher suites, SNI routing, SAN discovery, expiration tracking | `tlsAuditor.js` | | **HTTP Hardening** | Verb tampering (TRACE/OPTIONS), CORS misconfig, Host/X-Forwarded poisoning | `headersAuditor.js` | | **Service Discovery** | Non-destructive TCP banner grabbing (SSH, MySQL, Redis, DirectAdmin) | `bannerGrabber.js` | | **Client-Side SPA** | SPA route harvesting, dynamic `/api/*` extraction, React/Vue soft-404 detection | `semanticRouter.js`, `endpointHarvester.js` | | **XSS & DOM Taint** | Safe mathematical delimiter canaries (`__gbcanary_...`) with zero false positives | `canaryAuditor.js`, `domAuditor.js` | | **Access Control** | Unauthenticated mutation auditing, BOLA/IDOR permission boundary matrix | `authMatrixAuditor.js`, `dualSessionAuditor.js` | | **Business Logic** | Negative quantity underflow, client-controlled price tampering, coupon race stacking | `businessLogicAuditor.js` | | **Authentication** | JWT expiration, algorithm confusion (`none`), RSA $\to$ HMAC HS256 key downgrade | `jwtAuditor.js`, `jwtKeyConfusionAuditor.js` | | **OAuth & Identity** | OAuth 2.0 PKCE downgrade, open redirect URI boundaries, state tampering | `oauthPkceAuditor.js` | | **Server-Side Probes** | Statistical timing-differential SQLi, multi-step second-order stored injection | `sqliTimingAuditor.js`, `secondOrderAuditor.js` | | **Template & Logic** | Polyglot SSTI (Jinja/Twig/Smarty), Client-side prototype pollution gadgets | `polyglotSstiAuditor.js`, `prototypeGadgetAuditor.js` | | **SSRF & Callbacks** | Out-Of-Band (OAST) callbacks, Cloud Metadata traversal (IMDSv2, K8s, GCP) | `oastAuditor.js`, `cloudMetadataAuditor.js` | | **Protocols & Cache** | HTTP Request Smuggling (CL.TE/TE.CL), Web Cache Deception, CSWSH Hijacking | `httpSmugglingAuditor.js`, `webCacheAuditor.js`, `cswshAuditor.js` | | **API & Cloud** | GraphQL batching DoS / introspection, OpenAPI contract schema fuzzing | `graphqlAuditor.js`, `openapiFuzzer.js`, `subdomainTakeoverAuditor.js` | | **Proof & Compliance** | Photographic visual proof capture, SOC 2 Type II & ISO 27001 mapping | `visualProof.js`, `complianceMapper.js` | --- ### 🌊 Below the Surface: The Open Security Research Frontier Ghost Browser is designed as an open-source **force multiplier for red teamers, penetration testers, bug bounty hunters, and AppSec engineers**. Every offensive practitioner knows the frustration of spending 20 hours clicking buttons, enumerating subdomains, and writing repetitive boilerplate reports. Ghost Browser automates the repetitive reconnaissance and perimeter grind so researchers can focus their creative expertise on high-impact, complex logic flaws and earn higher bug bounties. We invite security researchers, tool authors, and community contributors to collaborate on these next-generation research frontiers: 1. **Stateful WebSocket Binary Frame Fuzzing (`CWE-1385`)**: - *Goal:* Mutate real-time binary payloads (Protobuf, MessagePack, custom framing) across active WebSocket sessions. 2. **AI Agent Prompt Injection & Tool Jailbreaks (`OWASP LLM01 / LLM02`)**: - *Goal:* Test AI-driven user interfaces for indirect prompt injection, tool calling privilege escalation, and system prompt leakage. 3. **WebAuthn, FIDO2 & Passkey Attestation Bypass**: - *Goal:* Audit WebAuthn registration and authentication flows for missing origin checks, challenge reuse, or RP ID spoofing. 4. **SAML 2.0 XML Signature Wrapping (`XSW`)**: - *Goal:* Probing enterprise SSO portals for XML entity expansion and assertion signature wrapping vulnerabilities. 5. **eBPF-Powered Kernel-Level Network & Memory Taint Tracing**: - *Goal:* Deep container inspection to monitor kernel syscalls and memory taint tracking during local containerized target runs. 6. **Mobile App Deep Link & Intent Scheme Injection**: - *Goal:* Audit custom URL schemes (`myapp://...`) and Android App Links / Universal Links for parameter injection and account takeover. 7. **Dynamic Multi-Step WAF Bypass & Payload Mutation**: - *Goal:* Genetic algorithm-based payload mutation to systematically evade Cloudflare, AWS WAF, and ModSecurity rule sets. 8. **GraphQL WebSocket Subscription Stream Injection**: - *Goal:* Test persistent GraphQL subscriptions for resource exhaustion and unauthenticated event eavesdropping. 9. **HTTP/2 & gRPC Multiplexing Desynchronization**: - *Goal:* Rapid-reset stream flooding (CVE-2023-44487 style) and gRPC header desync detection. 10. **Client-Side Storage & Token Cryptographic Tampering**: - *Goal:* Automated entropy analysis and session replay validation across encrypted IndexedDB and Web Crypto API stores. --- ### 🤝 How to Collaborate & Contribute Whether you're an AppSec engineer, red team operator, bug bounty hunter, or open-source developer: 1. **Explore the Iceberg**: Check out our research frontiers above or propose new ideas in [GitHub Issues](https://github.com/Wvdstoep/ghost-browser/issues). 2. **Follow the Non-Destructive Design Pattern**: All security tools in Ghost Browser must be non-destructive, safe for production environments, and emit reproducible `curl` PoCs and patch recommendations. 3. **Submit a Pull Request**: Check out `src/recon/` for examples of existing modules and unit test conventions. --- ## The agent The console has a second half: an agent that drives the same browser, in the same logged-in session, through the same numbered view the **Agent view** button shows a person. Every action it takes is "the number of the thing I mean", which is checkable and replayable — there are no selectors to get subtly wrong. **What it needs before it can run.** A model, in *Model*: Ollama Cloud (host `https://ollama.com` plus an API key) or a self-hosted Ollama (host only). The key lives on this browser's own volume and never comes back out of the API. *Test* proves the three settings work together before a job depends on them. **Who it works for.** A company profile — what you offer, who you want, where, what a good lead sounds like, and who never to approach. `signals` does the most work; `avoid` is the one nobody thinks to fill in and the one that prevents an embarrassing reply to a competitor. **Who it is.** *Study me* sends it to read the owner's own posts and comments and keep them verbatim. Those samples are what make a reply sound like the person rather than like software — a description of a writing style produces an imitation of a description. Everything it learns is readable, editable and deletable under *What it knows*. **More than one account.** Each stored profile can be labelled with the site it is signed in to. The agent lists them, and switches with `use_profile` when a job is about a site the current session is not logged in to — so "search LinkedIn" uses the LinkedIn login. ### The line that matters Reading is free. Commenting, joining, following, liking and messaging are not: they happen under a real name and the notification has already reached a person. So they go through `act`, which shows the exact text and waits. Approving with an edit is the normal case. That is enforced twice. The prompt says so, and a guard checks the label of anything the agent tries to click and turns a "Plaatsen" or "Lid worden" into a proposal anyway. The guard matches the START of a short label, because a substring match refused to let it open a post — "Open the post" contains "post". *Let it act without asking* removes the first line and keeps the record. It is off by default and should stay off until you have read a few of its drafts. ### Pacing Deliberately slow: 1–3 seconds between reads, 7–16 after anything that writes. Not a fingerprinting trick — a person does not open eleven posts in four seconds, and the accounts that get restricted are the ones that do. ### Which operating system a profile says it is Both Facebook's and LinkedIn's "was this you?" screens name the device, and both said Linux. Once the traffic leaves through the owner's own connection, that is the last thing still describing a datacentre — so a profile can be set to present as **Windows** or **macOS** (default: the truth). It goes through CDP's `Emulation.setUserAgentOverride`, never a user-agent string, because Chrome states its platform in three places — `navigator.userAgent`, `navigator.userAgentData` and the `Sec-CH-UA-Platform` header — and only that call sets all three together. Change one and the other two contradict it; a browser that disagrees with itself is a louder signal than an unusual OS. The Chrome version is read from the binary actually running, for the same reason. It does **not** make the browser undetectable. Canvas, fonts, WebGL, timing and TLS all still describe what this is. It removes one specific mismatch — the one both sites showed the owner — and it applies to popups too, since a sign-in window still announcing Linux gives it away at the exact moment it matters. Fixed at launch, so it needs a fresh session.