Documentation

Crossfyre docs

Everything to install the toolchain, bring nodes online, run distributed penetration testing workflows, and read the results. New here? Jump to the Quickstart, or walk through the tutorials instead.

Overview

Crossfyre is a hosted control plane for distributed penetration testing. You enrol your own machines as nodes; the platform orchestrates scan engines across them, and turns raw output into prioritized findings. Five engines ship today and chain into a single recon-to-vulnerability pipeline: voyage (subdomain enumeration), pulse (network scanning), mach (content discovery and crawling), scout (service enumeration and fingerprinting) and cortex (vulnerability scanning). The scan engines and node agent are open source; the orchestration, scheduling and dashboard are the hosted platform.

Recon is the commodity half. The part that finds the bugs other scanners miss is what sits on top of it: authenticated scanning so the surface behind a login gets tested, authorization testing for the BOLA and BFLA class that a single-identity scanner cannot see, out-of-band confirmation for blind vulnerabilities, origin discovery and browser-parity for targets behind a WAF, and traffic capture from a browser or an Android phone. Everything lands in one asset graph.

The pieces: the CLI (crossfyre) you install on a host, a node (that host, enrolled and running scans), engines (the scanners), workflows (.cfx scripts that drive a scan), findings (the results), and credits (the wallet for upcoming AI analysis; scanning itself is unlimited within your plan).

Quickstart

From nothing to a first finding. Budget fifteen minutes, most of it waiting for the scan.

1. Get a machine ready

You need one Linux host with Docker and root. A £5 VPS is enough to start; the box under your desk works too. This is the part people are surprised by, so it is first: Crossfyre does not run scans for you on our infrastructure, it runs them on machines you control. That is the whole design, and it is why your scans egress from your address and not a shared one.

2. Install and sign in

curl -fsSL https://get.crossfyre.io/install.sh | sudo bash
crossfyre login

login takes an API key, a username and password, or it can open a browser. Nothing else in the CLI works until it succeeds, by design.

3. Bring the node online

Create a node in the dashboard under Arsenal, copy the key it shows you once, then on the host:

sudo crossfyre node init

This installs the engines you selected, provisions the local database and registers the OS service. The dashboard flips the node to online when it receives the first heartbeat, usually within a few seconds. If it does not, crossfyre doctor is the next thing to run.

4. Run something

Start with subdomain enumeration against a domain you own. It is fast, it needs no wordlist, and its output is what everything else works from. In the dashboard: Operations, then Workflows, then Subdomain enumeration. From the terminal, crossfyre run does the same.

5. Read the result

Hosts land in the asset graph as they are found, not at the end. Findings appear under Intel with a severity and a confidence, and anything confirmed out of band says so. A workflow that dies partway through resumes rather than restarting, so a dropped connection costs you the gap and not the run.

Only run this against assets you own or have written permission to test. The vulnerability engine sends real payloads.

Requirements

  • OS: Linux or macOS (the Windows installer is experimental).
  • Docker: required. The engines persist scan state to a local database that the CLI runs as a Docker container, so install Docker before crossfyre node init (curl -fsSL https://get.docker.com | sh).
  • Root: needed to install the node service and set up isolated egress tunnels.

Installation

Linux and macOS:

curl -fsSL https://get.crossfyre.io/install.sh | sudo bash

Windows (PowerShell):

irm https://get.crossfyre.io/install.ps1 | iex

The installer downloads crossfyre and the node worker to /opt/crossfyre/bin (symlinking crossfyre into your PATH), verifying every binary's SHA-256 against the signed release manifest, and adds /opt/crossfyre/bin to your shell PATH. Prebuilt binaries are on the toolchain page; you can also build from source from the open repo.

CLI reference

One CLI drives everything. The most-used commands:

crossfyre loginAuthenticate the CLI to your account (API key, username/password, or browser).
crossfyre logoutRemove the saved session and stop/disable any installed engines.
crossfyre node initEnrol this host as a node using a node key from the dashboard. Installs the selected engines, provisions the database, and installs the OS service.
crossfyre node listList your fleet from the control plane, with live online/offline status.
crossfyre node statusShow the node daemons running on THIS host.
crossfyre node up / downStart / stop the node supervisor service (brings all local nodes online or offline).
crossfyre node restart / enable / disableRestart the service, or toggle start-on-boot.
crossfyre node remove [id] [--inactive]Remove a registered node from this host.
crossfyre extension listList engines with install state and daemon health.
crossfyre extension install <mach|voyage|pulse|scout|cortex|all>Download, checksum-verify and start an engine.
crossfyre extension remove / update / start / stop / restart <name>Manage an installed engine.
crossfyre run <script.cfx> <type:value ...>Run a .cfx workflow locally, no control plane required.
crossfyre trace --workflow-id <id> --token <t>Web Tracer: capture the sites you browse into a session's asset graph, through a local intercepting proxy.
crossfyre oast setupInstall your own OAST server as a service and obtain wildcard TLS, for a bring-your-own out-of-band endpoint.
crossfyre oast serve / statusRun your OAST server in the foreground, or show its state.
crossfyre update [self|all|<ext>]Update the CLI, the node binary, and engines from the signed release manifest.
crossfyre statusOverview of local node daemons, engines and the database.
crossfyre db <up|down|start|stop|restart>Manage the toolchain database container.
crossfyre doctorDiagnose the environment: Docker, database, release-CDN reachability, PATH.
crossfyre uninstall [--purge]Remove services, engines, binaries and the database container.

Nodes

A node is one of your hosts, enrolled to run scans. Create it in the dashboard (Nodes), then run sudo crossfyre node init on the host and paste the node key. Enrolment installs the engines you selected, provisions the local database, and installs an OS service so the node survives reboots.

The node service runs a supervisor that keeps every registered node online; each reports a heartbeat so the dashboard shows it online or offline. Bring them up or down with crossfyre node up / crossfyre node down, check local daemons with crossfyre node status, or the whole fleet with crossfyre node list.

OPSEC: a node can route outbound traffic through proxy chains and isolated VPN tunnels, so scans leave from where you choose and never touch the host's own network.

Proxies & egress

Where your scans appear to come from is yours to decide. A node can route target-reaching traffic through proxy chains (HTTP, HTTPS, SOCKS4, SOCKS5) or through an isolated VPN tunnel, so traffic leaves from where you choose and never from the host's own network.

Manage proxies from the Proxies page: add them individually or in bulk, tag them, group them into ordered chains, test connectivity on demand, and schedule recurring health checks so a dead proxy is flagged before a scan depends on it.

Egress isolation. In a multi-tenant platform the rule that matters is that probes which touch your target leave from your infrastructure, not from shared control-plane infrastructure. Crossfyre is built that way: the control plane orchestrates, your nodes do the reaching.

Bring your own egress. A node can be pointed at your own residential or mobile proxy for the traffic that reaches a target. It is always opt-in, and it is off unless you configure it.

These features exist so an authorized test reaches the in-scope application and stays in scope. They are source-IP and routing control for engagements you are contracted to run, not a way to avoid attribution.

Workspaces & teams

A workspace is the isolation boundary for work: its own assets, findings, workflows and history. Keep one per client, per programme, or per environment, and switch between them from the workspace picker. Nothing leaks across a workspace edge.

A Team Space adds people: shared nodes, wordlists, credentials and findings, with role-based access, an activity log, and per-member permissions. Leaders manage members and billing; members run work. Seats and workspace counts are set by your plan.

Invite teammates from Team Space; they join with the invite code emailed to them. Organizations add multiple teams, an org console and shared billing.

Organizations

A personal plan covers your own workspaces and your own arsenal. An organization is a separate billing entity with member seats, teams and shared team workspaces, and it is what you want the moment a second person needs to see the same findings.

You can hold a personal plan and be a member of an organization at once. Your own work stays on your plan; work inside the org is covered by the org. Seats, teams and workspace counts are set by the org plan rather than by the members' individual ones.

Syndicate is prepaid and self-serve: you choose seats and limits up to the plan maximum, and usage pauses instead of overspending. Enterprise is postpaid, provisioned during onboarding and invoiced. Both are managed from the org billing page rather than your personal one.

Scan engines

Engines are the scanners. Each is a standalone, open-source tool that runs as a local daemon, keeps its work in the toolchain database, and can run entirely on its own from the terminal. Enrol a host as a node and the platform supervises the same engines across your fleet, paces each scan to what the target can take, and streams every result into one shared asset graph. Install and manage them with the CLI (crossfyre extension install <name>); each runs a live terminal UI standalone and reports to your dashboard on the platform.

The five shipping engines chain into a single recon-to-vulnerability pipeline, and each also stands on its own:

voyageSubdomain enumeration. Passive intel sources plus active brute-force. Finds the hostnames.
pulseNetwork and port scanning. Finds live hosts, open ports and the services on them.
machContent discovery and crawling. Finds hidden paths and maps each web app's surface.
scoutService enumeration and fingerprinting. Identifies the tech, versions and CVE leads.
cortexVulnerability scanning. Runs detection templates and authorization tests, and confirms them.

The pipeline in one line: voyage finds subdomains, pulse finds open ports and services, mach discovers content and crawls each web service, scout fingerprints the tech and versions, and cortex checks the surface for vulnerabilities. Every engine is stateful and resumable: a scan you stop, or one interrupted by a dropped node, picks up exactly where it left off.

Full reference for each engine: flags, sources, tuning and what each one does not do.

Authenticated scanning

Most of an application is behind a login, and an unauthenticated scan never sees it. Crossfyre stores credentials in your arsenal and signs in for you, so the session-gated surface actually gets tested.

What it supports

  • Static tokens and API keys, sent as headers or cookies.
  • Form logins, for applications that just want a username and password posted.
  • OAuth2 / OIDC, non-interactive (client credentials, password grant) and interactive (authorization code).
  • SSO and MFA flows, driven by a headless broker.

How your secrets are handled

Credentials are encrypted at rest. When a scan needs to authenticate, the broker performs the sign-in and hands the engine only a resolved token; your raw secrets are never put on the message bus and never reach an engine. Credentials are scoped to a workspace, and to the hosts you attach them to.

Using it

Add a credential under Arsenal → Credentials, attach it to the hosts it applies to, and select it when you launch a scan. The Web Tracer can also seed a session you already have: browse the target while capturing and the cookies and bearer headers you used can be stored as an arsenal credential for later scans.

Authenticated scanning unlocks on Pro. The gate is enforced server-side, not hidden in the UI.

Authorization testing (BOLA / BFLA / BOPLA)

The bugs that matter most in an API are usually not missing headers; they are one user being able to read or do something that belongs to another. A scanner that logs in as a single identity cannot see them, because the response looks like a perfectly healthy 200.

Crossfyre runs authorization testing as a mode inside a scan. You give it several identities (say admin, user A, user B, and anonymous), it replays each endpoint as every identity, and it diffs the responses. What it is looking for:

  • BOLA (broken object level authorization): user B retrieves user A's object by changing an id.
  • BFLA (broken function level authorization): a lower-privileged identity reaches a privileged action.
  • BOPLA / mass assignment: fields a caller should not be able to set are accepted, or fields they should not see come back.
  • Excessive data exposure: the endpoint returns more than the caller is entitled to.

Coverage spans REST paths, query parameters and GraphQL, and every candidate goes through the same confirm-before-report step as the rest of cortex, so what reaches your findings is what reproduced.

Setting it up

Add one credential per identity in the arsenal, label the role, and select them when you launch the scan. The more distinct the privilege levels you give it, the more it can tell you.

Authorization testing unlocks on Pro, and is enforced server-side.

Out-of-band confirmation (OAST)

Some vulnerabilities produce no visible response: a blind SSRF, a blind command injection, an out-of-band SQL injection. The only proof is the target reaching out to a server you control. That is what OAST is for.

cortex injects a unique callback address into the payloads it sends, then watches for the DNS or HTTP interaction that confirms the target actually executed it. No interaction, no finding.

Managed or your own

  • Managed pool: nothing to run. Available on paid plans.
  • Bring your own: point a scan at an OAST endpoint you operate.
  • Self-hosted: run the open-source server yourself on your own domain with crossfyre oast setup, which installs it as a service and obtains wildcard TLS. Self-hosting is free on every plan.

Zero-knowledge by design

Interactions are sealed to a per-scan key. Even the operator of the OAST server holds only ciphertext, so running the managed pool does not mean we can read what your targets sent. Manage endpoints from the OAST page in your dashboard.

Reaching hard targets

An authorized scan is not much use if the edge drops it before it arrives. Two things get in the way: the target sits behind a WAF or CDN, and a scanner announces itself as a scanner.

Origin discovery

voyage can work out a target's real origin behind a CDN, which lets a scan reach the application directly. It is also worth reporting on its own: an origin that answers the public internet without the edge in front of it is an exposure.

Looking like a browser

Rather than presenting the fingerprint of a scanning library, Crossfyre can present a genuine browser handshake, so an authorized scan is not rejected purely on how the client looks. It will not solve an interactive challenge you have not been authorized to solve, and it is not a way to bypass access controls: what it does is stop a legitimate test being discarded at the edge.

Pacing

Throughput is adapted continuously to what the target is actually tolerating, rather than fixed at a number you guessed. That keeps a run fast without hammering any single host, and it is what lets a large distributed scan finish instead of collecting rate-limit errors.

The Evasiveness switch

Evasion is a per-scan setting, so you can turn it down for a target that does not need it. Browser-impersonation is a Reaper capability; adaptive pacing runs on every plan, at a level set by your tier.

These capabilities exist so an authorized scan reaches the application it was contracted to test. Use them only within a scope you have written permission for.

Workflows

A workflow is a .cfx script (Python) that drives a scan: it picks targets, calls the engines, and reports results. Run one locally with crossfyre run content-discovery.cfx url:https://example.com, or launch it from the dashboard to run across your nodes.

Workflows are crash-safe: the platform reserves an estimated cost at launch and reconciles the actual work at completion (reserve-then-reconcile). A dropped node or a crash resumes where it left off, and you are never charged twice or for work that did not run. Schedule a workflow to run on a recurring basis and have results pushed to you.

What you can run

Ten workflow types ship today. Each has a create form in the dashboard under Operations, and each maps onto one or more engines:

subdomain-enumPassive and active subdomain discovery. Usually the first stage, because everything downstream works from its output.
port-scanLive hosts, open ports and the services behind them, spread across the fleet rather than run fast from one box.
content-discoveryHidden paths and files, rate-adapted per target so a wordlist does not get you blocked.
web-crawlMaps a web application by following it, producing the endpoint and parameter surface the testing stages need.
service-enumFingerprints technology and versions on what was found, and turns that into CVE leads.
vuln-scanDetection templates plus the injection oracle, with out-of-band confirmation where the class allows it.
api-testDrives an API from a spec or a capture, so endpoints get tested as endpoints rather than as URLs.
origin-discoveryFinds the real origin behind a CDN or WAF. Often the highest-value single result on a target, and the exposure is itself reportable.
web-tracerCaptures traffic from a browser or a phone and feeds the real request shapes into the graph. See Traffic capture.
customYour own .cfx script, when the built-in shapes do not fit.

Authenticated scanning, authorization testing and advanced evasion are capabilities that apply within these workflows rather than separate types. Which ones you can switch on depends on your plan.

Routines

A routine is a scan you do not want to remember to run. Chain stages into a schedule (recon on Monday, a vulnerability pass when it finishes) and the platform runs the whole thing on your fleet and pushes you the results.

Because each stage feeds the next, a routine is how most people keep an attack surface current: new subdomains get ports scanned, new endpoints get crawled, and anything that changed since last time shows up in the asset feed. Create and manage them from the Routines page.

Routines unlock on Pro.

Missions

A mission is a routine with a memory. Where a routine runs stages on a schedule, a mission chains them with data passing: the hosts one stage discovers become the targets of the next, with per-stage node assignment, its own schedule, and a full run history you can go back through.

Use the Planner to compose one and to bulk-launch work across a set of targets rather than starting scans one at a time.

Missions are a Reaper capability, enforced server-side at launch, on schedule, and on re-run.

Traffic capture (Web Tracer and Mobile Tracer)

The engines map a target from the outside. The tracers capture it from the inside: they man-in-the-middle your own live traffic behind a per-session CA and feed every request into the same asset graph, so the endpoints, operations and parameters a real session touches become assets a scan can target.

Modes

Capture is opt-in per workflow. Passive (the default) reduces traffic into assets and holds nothing. Full capture persists complete request and response pairs into a Requests table, and can hold traffic at an intercept gate so you can modify and forward, or drop, each request (manually or auto-approved).

Bench and the Repeater

Send any captured request to Bench to replay and mutate it. Unlike a browser-based repeater, Bench runs the request through a node you choose, so replays inherit the same egress and pacing as the rest of your fleet.

Mobile Tracer (Android)

The Crossfyre Tracer app turns a phone into a capture node with no laptop in the loop. It uses Android's VpnService to route the device's own traffic through an on-device MITM, scoped to the apps you pick, and pairs to a workspace by QR code.

Certificate-pinned apps. Android 7+ does not trust user-installed CAs by default, and a pinned app trusts only its own certificate, so ordinary on-device capture sees nothing from it. Tap patch and the phone uploads that app's split APKs with the session CA; the patch service rewrites and re-signs the app so it trusts your session certificate, and returns installable splits that the phone reinstalls (uninstall then install, because the signature changes). No root, no PC, no Frida attach.

App files you upload are processed in a temporary working directory that is deleted when the job finishes, whether it succeeds or fails. Android only. Use it only on apps you own or are authorized to test.

Bench & Repeater

Capture gets you the request. Bench is where you do something with it.

The Requests table holds everything a capture session recorded, with full bodies when full capture is on. Anything in it can be sent to the Repeater, which re-issues a request with whatever you change and shows the response beside it. The Repeater is built around tabs and history, so a series of attempts is a series you can go back through rather than one box you keep overwriting.

Requests execute on the node, not from your browser. That matters more than it sounds: the request leaves from the same address, with the same egress and the same TLS identity, as the scan that found the endpoint. A request that works in your browser and fails from the node is telling you something real.

Interception is a separate switch. With it on, a matching request pauses so you can edit it before it goes out.

Asset graph

Every engine writes into one shared asset graph rather than its own silo. A domain leads to hosts, hosts to ports and services, services to endpoints, and endpoints to the operations (a method against a path) and the parameters each one takes. That is what makes the pipeline more than five tools in a row: scout knows what mach found, and cortex knows what both of them found.

Views

  • Assets: browse and filter everything discovered, and open any asset for its full context and history.
  • Attack surface: the same graph as a map, for seeing shape and reach rather than rows.
  • Overview: the same graph reduced to counts, a feed of what changed, and a ranked list of what to look at next.

What changed

Assets are content-hashed at ingest, so a re-run does not just add rows: it produces a typed diff. New hosts, endpoints that disappeared, a service whose version moved, a response shape that changed. The change feed is usually the fastest way to see what a target did since you last looked.

Traffic capture feeds the same graph (see Traffic capture), so a surface you browsed and a surface you scanned are one picture.

Findings

Results land in the Findings explorer: filter by severity, by active or passive discovery, and by host; search, paginate, and export the set to CSV, JSON or Markdown for your report or pipeline.

Valkyrie triage

A scanner's output is a queue, and the work is deciding which twenty of two hundred findings are worth an afternoon. Valkyrie reads the findings in a workspace and ranks them, with the reasoning attached rather than a bare score.

It is metered separately from scanning. Scanning within your plan limits is unlimited and costs no credits; triage consumes AI credits, which your plan grants each term and which you can top up. That split is deliberate, so an expensive feature cannot make an ordinary scan expensive.

Triage reads findings that already exist. It does not send traffic at a target and it cannot turn an unconfirmed finding into a confirmed one.

Import

Most engagements do not start from zero. Import brings an existing list of hosts, endpoints or an API specification into a workspace so the asset graph starts populated and the first scan has something to work from.

Imported assets carry their provenance. An endpoint you supplied from a spec is marked as coming from a spec, not as something observed, and the distinction survives into findings: a parameter the platform saw in real traffic is stronger evidence than one a document claimed exists.

Notifications

Get alerted the moment a scan finishes or a finding lands, on the channel you already live in:

  • Discord / Slack: add the Crossfyre bot, run /login <email> and confirm with the code we email you (/verify). Subscribe a channel and alerts post there.
  • Email: enable email alerts in Settings → Notifications.

Manage channels and what triggers an alert from the Notifications page in your dashboard.

Wordlists

Crossfyre ships default wordlists and lets you upload your own, scoped to your team. Engines (mach, voyage) pull from them during active discovery. Manage them from the Wordlists page.

Extensions

Engines are installed on a node as extensions. crossfyre extension install voyage from the terminal, or subscribe from the marketplace in the dashboard under Arsenal and the node picks it up.

The marketplace lists what is available and what a node already has. The five core engines are the ones that matter today; the extension mechanism is the same one they use, which is what makes adding more of them a packaging question rather than a platform change.

Scan defaults

Every workflow form starts pre-filled. Those values are yours to set, per user, from Operations then Settings: thread counts, target ceilings, timeouts, which stealth level to use, and whether a stage runs at all.

Worth setting once early. The defaults are conservative on purpose, and if you find yourself changing the same three fields on every launch, that is the page to change instead.

A saved default that names a capability your plan does not include is ignored rather than failing the launch.

Usage & status

The Usage page shows what you have consumed against your plan's ceilings: workflows this month, concurrent runs, nodes, proxies, wordlist storage and credits. It is the page to check before a large engagement rather than after one stops early.

The Status page reports the control plane's own health, and the dashboard reads it to explain itself: if a scan will not start because the platform is degraded rather than because of your configuration, that page is where it says so. It is also public at status.clickswave.org.

Billing & credits

Your plan sets your limits (nodes, concurrent workflows, storage, seats) and drops a monthly batch of credits into your balance. Scanning is unlimited within your plan limits: there are no per-scan fees. Credits are a separate wallet reserved for AI-assisted analysis, and they never expire.

  • Free: 2 nodes, 2 concurrent, 200 credits / month.
  • Pro: 10 nodes, 10 concurrent, 1,500 credits / month.
  • Reaper: 20 nodes, 50 concurrent, 5,000 credits / month.

Organizations run on Syndicate (a base price carrying three seats, then per seat) or Enterprise instead. Top up credits any time. Prices, seat counts and the full limit matrix live on the pricing page, which is the source of truth.

Not built yet

Taken from the same internal status table the landing page publishes, so this list says what is missing rather than what is planned.

Managed nodes and proxy pools

Not built

Today every node is one you enrol yourself, on a Linux host with Docker. Managed nodes would remove that step. The deploy page shows the option disabled rather than pretending otherwise.

Aggregated reporting

Not built

Findings export per workspace. A single client-ready PDF across an engagement does not exist.

Public partner API

Not built

The dashboard and the CLI both talk to the control plane, but there is no documented API for anyone else to build against.

Two-factor authentication

Not built

Worth stating plainly on a security product: the settings page has the row and it is locked.

Self-hosted control plane

Not built

The engines and the OAST server are open and self-hostable. The control plane is not.

Half built

These exist and you will notice the gap:

  • Custom .cfx workflows run, but the create card in the dashboard is still locked.
  • Discord and Slack alerts are implemented and no bot token is configured in production, so email is the delivery that works.
  • Findings retention runs in report-only mode in production: it logs what it would remove and removes nothing, so the plan retention windows are not yet enforced.
  • Priority execution and the per-tier adaptive levels are not differentiated yet.

Troubleshooting

Start with crossfyre doctor, which checks Docker, the database container, release-CDN reachability and your PATH.

  • node init fails / engines won't start: Docker isn't installed or running. Install it (get.docker.com) and start the daemon.
  • node shows offline: check the service with crossfyre node status; bring it up with sudo crossfyre node up.
  • command not found after install: open a new shell so /opt/crossfyre/bin is on your PATH (crossfyre is also linked into /usr/local/bin).
  • dashboard says systems offline: the control plane is unreachable; the in-app status page shows what's down.

Support

Questions or stuck? Join the Discord, or email team@crossfyre.io. Found a security issue? Email team@crossfyre.io privately (see the toolchain repo's SECURITY policy).