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.

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

  1. Create an account at crossfyre.io.
  2. Install the CLI:
    curl -fsSL https://get.crossfyre.io/install.sh | sudo bash
  3. Authenticate:
    crossfyre login
  4. In the dashboard create a node, copy its key, then enrol this host:
    sudo crossfyre node init
  5. Start a workflow from the dashboard (or crossfyre run), then watch findings stream in and get notified when it finishes.

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.

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.

voyage

Subdomain enumeration · daemon port 4442 · open source · crossfyre extension install voyage

voyage maps a domain's subdomains two ways at once. Passive enumeration pulls known hostnames from public intelligence sources; active enumeration brute-forces candidates from a wordlist and confirms the ones that resolve. Each discovered subdomain is reported with the source that found it, so you know whether it came from certificate transparency, passive DNS, or a live resolution. It is usually the first stage of a run: its output is the target list everything downstream works from.

Passive sources

Passive enumeration is fast, quiet, and needs no wordlist. voyage queries public sources and keeps only real subdomains of your target:

  • crt.sh: certificate-transparency logs (every hostname that ever appeared in a TLS certificate for the domain).
  • hackertarget: passive DNS and host search.
  • AlienVault OTX: passive DNS records.

No API keys are required. Drop a single source with --exclude-passive-source, or skip passive entirely with --disable-passive-enum.

Active enumeration

Active enumeration takes each word in your wordlist, forms word.domain, and confirms it with a sequence of techniques. The first technique that succeeds marks the host found and records which one confirmed it:

  • ipv4_lookup / ipv6_lookup: DNS A / AAAA resolution.
  • http_probing / https_probing: an HTTP / HTTPS request on the ports you choose (defaults 80 / 443).

Exclude any technique with --exclude-active-technique, or skip the active phase with --disable-active-enum. You cannot disable both phases at once.

Standalone usage

voyage --daemon &                      # start the engine (port 4442)

# passive sources + active brute-force
voyage scan -d example.com -w ./subdomains.txt -t 32

# passive only (no wordlist needed)
voyage scan -d example.com --disable-active-enum

# active only, on custom probe ports
voyage scan -d example.com -w ./sub.txt --disable-passive-enum --http-probing-port 80,8080 --https-probing-port 443,8443

Key options

-d, --domainTarget domain to enumerate.
-w, --wordlist-pathWordlist for the active brute-force (required unless active is disabled).
-t, --tasksConcurrent workers for the active phase.
--disable-passive-enum / --disable-active-enumTurn either phase off (not both).
--exclude-passive-sourceDrop a source: crt.sh, hackertarget or alienvault.
--exclude-active-techniqueDrop a technique: ipv4_lookup, ipv6_lookup, http_probing, https_probing.
--http-probing-port / --https-probing-portPorts the HTTP / HTTPS probes hit. Defaults 80 / 443.
--fresh-startDiscard saved state and start clean (the default resumes).

Output

Each finding is a subdomain plus the source that confirmed it. Results stream to the live UI and into the toolchain database; on the platform they land in the shared asset graph and become the seed for the next stage. Passive and active results are merged and de-duplicated, so a host found by both counts once.

pulse

Network & port scanning · daemon port 4443 · open source · crossfyre extension install pulse

pulse scans hosts and ports to find what is open, closed or filtered, and can identify the service and grab a banner on each open port. It takes single hosts, hostnames or IPv4 CIDR ranges as targets, and port ranges, lists, or the built-in presets. On the platform, large scans are paced by the engine to the network path, so a scan runs fast on a healthy link without turning a slow-but-open port into a false negative.

Standalone usage

pulse --daemon &                       # start the engine (port 4443)

# top-1000 ports on a host
pulse scan -t example.com

# a CIDR block, explicit ports, service + banner detection
pulse scan -t 10.0.0.0/24 -p 22,80,443,8080 --service-detection

# a full sweep of several targets
pulse scan -t 10.0.0.5 10.0.0.6 -p all

The live UI shows a progress gauge, an open / closed / filtered tally, and a table of open and filtered ports with service, latency and banner. Closed ports are counted but not listed, to keep the table focused on what matters.

Targets and ports

  • Targets (-t): hostnames, IPv4 addresses, or IPv4 CIDR blocks such as 192.168.1.0/24. Pass several, space-separated.
  • Ports (-p): a range (1-1024), a list (80,443,8080), or a preset: top-100, top-1000 (the default), or all for every port.
  • Service detection (--service-detection): identifies the service on each open port and records the banner the server sends back.

Key options

-t, --targetsHosts, IPs or CIDR ranges. Repeatable.
-p, --portsRange, list, or top-100 / top-1000 / all. Default top-1000.
--service-detectionIdentify the service and grab the banner on open ports.
--tasksHow many probes run in parallel. Higher is faster and louder.
--timeoutPer-probe timeout in milliseconds. Raise it on high-latency links.
--delayDeliberately slow the scan by pausing between probes.

Postures

When run on the platform, a single dial sets how hard pulse is allowed to push, and the engine works within that envelope:

  • stealth: stay quiet and low-footprint.
  • balanced: the default middle ground.
  • throughput: open up and go as fast as a healthy path allows.

On the platform

Run pulse as a network-scan workflow across your fleet; the open web services it finds become targets for scout and cortex. Pick a posture and the platform sets the pace for you, so you don't hand-tune concurrency for every target.

mach

Content discovery & HTTP fuzzing · daemon port 4441 · open source · crossfyre extension install mach

mach is a stateful HTTP content-discovery and fuzzing engine. Point it at a URL with a FUZZ marker and a wordlist; it substitutes each word into the marker, fires the requests concurrently, and reports every path that comes back with a status you accept. Because each candidate request is recorded as it runs, a scan you stop resumes exactly where it left off and never re-tests a path it already checked. The same engine also powers wordlist-free crawling.

The FUZZ marker

mach replaces a single placeholder, ::FUZZ:: by default, with each word from your wordlist. Put it anywhere in the URL to control what you are fuzzing: leave it out and mach appends it to the path for classic directory discovery, or place it inside a path segment or a query value to fuzz there instead. Change the marker with --fuzz-marker if ::FUZZ:: collides with your target.

Standalone usage

mach --daemon &            # start the engine (port 4441)

# directory / file discovery (the marker is appended if you omit it)
mach scan --url https://target.tld --wordlist-path ./common.txt --tasks 20

# place the FUZZ marker to control exactly what you fuzz
mach scan --url "https://target.tld/::FUZZ::/login" --wordlist-path ./dirs.txt
mach scan --url "https://target.tld/search?q=::FUZZ::" --wordlist-path ./payloads.txt

The live UI shows progress, a found / not-found / error tally, and a table of hits with status code and response size. Press l for logs and q to quit.

Key options

-u, --urlTarget URL(s). Repeatable. The FUZZ marker is appended to the path if absent.
-w, --wordlist-pathWordlist file, one candidate per line.
--fuzz-markerThe placeholder each word replaces. Default ::FUZZ::.
--http-methodget, post, put, delete or head. Default get.
--success-status-codesComma-separated status codes counted as a hit. Defaults to the 2xx / 3xx range.
-t, --tasksConcurrent workers. Higher is faster and louder.
-i, --intervalDelay in milliseconds between requests per worker.
--headers / --cookies / --basic-authRequest headers, cookies, and HTTP basic auth for reaching authenticated paths.
--follow-redirects / --follow-redirects-depthWhether to chase redirects, and how deep (default 5).
--random-user-agent-requestRotate a random User-Agent per request, or set one with --user-agent.
--fresh-startIgnore saved state and rescan from scratch (the default resumes).
--adaptive-rateLet mach adapt its concurrency and delay to the target's live health instead of a fixed rate.
--postureHow aggressive the adaptive controller is: stealth, balanced or throughput.

Output

Each result records the resolved URL, its scan status (found / not found / error), the HTTP status code, and the response and header sizes. mach classifies purely on the status codes you accept, so tune --success-status-codes to your target. Many engagements want 401 and 403 counted as interesting rather than ignored. Results are kept in the toolchain database and stream live; on the platform they land in your Findings explorer.

Crawling

Beyond wordlist fuzzing, mach can crawl a web app without a wordlist: it walks the site by following links, forms and the endpoints embedded in pages and JavaScript, mapping the reachable surface. On the platform this is the web-crawl workflow, and its output feeds scout and cortex the live URLs to work on.

On the platform

Run a content-discovery or web-crawl workflow from the dashboard and mach runs across your nodes against the targets you pass in, with the platform pacing it to the target and reserving credits for the work actually done.

scout

Service enumeration & fingerprinting · daemon port 4444 · open source · crossfyre extension install scout

scout takes a live web service and works out what it is running. It fetches the target, reads the signals a server gives away (headers, cookies, the HTML, the generator meta tag, the favicon) and matches them against a curated signature set to identify the web server, language, framework, CMS and JavaScript libraries in use, with versions wherever the target exposes them. From each product and version it derives version-based CVE leads, detects the WAF, CDN or load balancer in front of the service, and computes a Shodan-compatible favicon hash for pivoting. It is the enrichment stage between discovery and vulnerability scanning.

What it detects

  • Technologies and versions: web servers (Nginx, Apache, IIS, Tomcat and more), languages and runtimes (PHP, Java, Python, Node.js), frameworks (ASP.NET, Laravel, Django, Rails, Spring, Express), CMSes (WordPress, Drupal, Joomla, Magento) and JS libraries (React, Vue, Angular, Next.js, jQuery). A detected technology pulls in the ones it implies: WordPress implies PHP and MySQL, Tomcat implies Java.
  • CPEs: each detection emits a CPE identifier carrying the detected version, the join key that CVE matching pivots on.
  • WAF / CDN / load balancer: passively identifies the edge and protection vendor in front of a service (Cloudflare, Akamai, CloudFront, Fastly, Sucuri, Imperva, F5 BIG-IP, ModSecurity) from its tells.
  • Favicon hash: an mmh3 hash compatible with Shodan's http.favicon.hash, plus MD5, for correlating hosts across your surface.
  • CVE leads: for each detected product and version, scout matches a version-ranged CVE ruleset and flags the versions that fall in a vulnerable range.

CVE leads are marked version-inferred, not confirmed: they flag that a version sits in a vulnerable range, but a backported patch can make that a false positive. They are leads for cortex to confirm, not final findings. The ruleset ships with a starter set and can be extended at runtime by pointing SCOUT_CVE_FILE at your own JSON rules, with no rebuild.

Standalone usage

scout --daemon &                       # start the engine (port 4444)

# fingerprint a single service
scout fingerprint https://example.com
scout fingerprint example.com:8443

# full control: timeout, redirects, favicon, probing depth
scout exec '{"operation":"fingerprint","target":"https://example.com","depth_tier":2,"favicon":true}'

Probing depth

The depth_tier parameter controls how much active probing scout does against a target: 0 passive (only the signals in the landing response), 1 quiet (adds the favicon fetch), 2 standard (the default), 3 aggressive. Lower tiers are quieter against sensitive targets. A per-request timeout_ms and a follow_redirects toggle round out the knobs, and an auth object lets scout fingerprint the authenticated surface.

Output

scout emits four kinds of finding: a technology record per detection (name, category, version, CPE, confidence and the evidence that matched), a service summary (status, title, server, WAF/CDN, favicon and the tech list), a vulnerability record per CVE lead, and an environment record that tells the vulnerability scanner how to behave: whether a WAF is present, which status codes that WAF blocks with, and a recommended pace.

On the platform

scout runs after discovery: it takes the live web services that pulse and mach surfaced, enriches each one, and writes the results into the shared asset graph. Its environment record is what lets cortex pace itself sensibly against a WAF-fronted target, and its CPEs tie a detected version to the checks that matter.

cortex

Vulnerability scanning · daemon port 4445 · open source · crossfyre extension install cortex

cortex is the vulnerability-scanning engine, a dynamic scanner that runs detection templates and dedicated authorization tests against a target and reports evidence-backed findings. It reads nuclei-format templates (its own curated built-ins plus any external directory you point it at), matches on response status, body content, size, regexes and an expression language, and confirms blind vulnerabilities out-of-band. Beyond templates it has a purpose-built authorization engine that replays endpoints across multiple identities to catch broken access control. Every candidate is put through a correctness pass before it is reported, so findings are evidence-backed rather than "possible".

The template model

cortex runs a practical subset of the nuclei YAML template schema, so templates you already have will largely work. A template declares an id, some info (name, severity, description), and one or more HTTP requests:

id: git-config-exposure
info:
  name: Exposed .git/config
  severity: medium
http:
  - method: GET
    path:
      - "{{BaseURL}}/.git/config"
    matchers-condition: and
    matchers:
      - type: word
        words: ["[core]", "repositoryformatversion"]
        condition: and
      - type: status
        status: [200]

Requests support method, a list of paths, headers, a body, and payloads, named value lists substituted into {{placeholders}} across the path, body and headers, which cortex expands into concrete requests (bounded for safety). Placeholders include {{BaseURL}}, {{RootURL}} and {{Hostname}}, your own payload names, and {{interactsh-url}} for out-of-band checks. External templates load from the directory set with templates_dir or the CORTEX_TEMPLATES_DIR environment variable, on top of the built-in set (which always runs). The built-ins cover common high-signal exposures: .git/config and .env files, private keys and cloud credentials, backup files, directory listings, phpinfo and server-status pages, debug stack traces, path traversal and blind SSRF.

Matchers

A matcher decides whether a response is a hit. cortex supports:

statusThe response status code is in a given list.
wordThe response contains given substrings (combined with and / or).
regexThe response matches given regular expressions.
sizeThe response body length is one of given sizes.
dslA boolean expression over the response (see below).

Each matcher can target a part of the response (body, headers, or the whole raw response), can be combined with and / or via matchers-condition, and can be marked negative to require that something is absent.

The expression DSL

The dsl matcher evaluates a boolean expression against the response, for checks a plain word or status match cannot express, for example status_code == 200 && icontains(body, 'werkzeug'). It exposes response variables (status_code, body, headers, content_length), the usual comparison and logical operators, and helper functions including contains, icontains, startswith, endswith, contains_any, contains_all, regex, len, tolower and trim.

Out-of-band confirmation

Some vulnerabilities never show in the response: the target just makes an outbound request if it is vulnerable. cortex confirms these by embedding a unique out-of-band callback URL in the payload ({{interactsh-url}}), firing the check, and watching for the callback. A received callback is high-confidence proof the vulnerability fired: this is how cortex confirms blind SSRF, blind injection and similar flaws. cortex never reports a blind finding without a real callback, so there are no phantom out-of-band alerts. Out-of-band checks run when an out-of-band endpoint is configured for the engine; otherwise those templates are safely skipped.

Authorization testing (BOLA & BFLA)

cortex includes a dedicated authorization engine, separate from templates, that is hard to test any other way. It takes a set of endpoints and a set of identities (each a role plus its login), replays every endpoint as every identity, and compares the responses to find broken access control:

  • BOLA / IDOR (object-level): two different users get the identical response body for an object-scoped endpoint (like /invoices/3), meaning the object is not scoped to its owner. Reported critical. cortex spots object references both in the path (numeric ids, UUIDs, opaque handles) and in query parameters (?account_id=…, anything ending in _id), and is precise enough not to flag ?page=2.
  • BFLA (function-level): a non-privileged identity reaches a privileged endpoint (/admin, /manage, /internal and the like) that a privileged identity also reaches, proving it is a live function and not a 404. Reported high.
  • Broken authentication: an anonymous request reaches a protected endpoint that should require a login. Reported high.

Every finding carries a per-identity response matrix (who got which status and body size) as its evidence, and cortex guards against false positives from soft "please sign in" pages and login redirects.

Correctness and resilience

cortex is built to be trusted, not just noisy. Every candidate goes through a generate, detect, confirm, report pass: a response-based match is re-issued and must reproduce before it becomes a finding; an authorization candidate is re-probed as the accused identity; a blind check must produce a real callback. And it is resilient to rate limiting: on a 429 or 503 it backs off and retries rather than giving up, so a busy or WAF-fronted target does not quietly hide real vulnerabilities. The result is a low false-positive rate and findings you can put straight into a report.

Standalone usage

cortex --daemon &                      # start the engine (port 4445)
cortex scan https://example.com

# high/critical only, external templates, authenticated
cortex exec '{"operation":"scan","target":"https://example.com","severity":["high","critical"],"templates_dir":"/opt/nuclei-templates","auth":{"headers":{"Authorization":"Bearer <token>"}}}'

# authorization testing across two identities (BOLA / BFLA)
cortex exec '{"operation":"authz","endpoints":[{"method":"GET","url":"https://api.example.com/invoices/3"}],"identities":[{"role":"user_a","auth":{"cookies":"session=a..."}},{"role":"user_b","auth":{"cookies":"session=b..."}}]}'

Key options

targetURL or host:port to scan.
severityRestrict to given severities such as high or critical. Empty runs all.
templates_dirExternal nuclei template directory, in addition to the built-ins.
passive_onlyOnly run passive header checks; make no active requests.
authHeaders and cookies for authenticated scanning.
timeout_ms / follow_redirectsPer-request timeout and whether to follow redirects.

Output

Each finding carries the target, severity, name, the template id that fired, the exact URL it matched at, a description and evidence, all marked confirmed. Passive checks also flag missing security headers (CSP, HSTS, X-Frame-Options, X-Content-Type-Options). On the platform, cortex runs as a vulnerability-scan workflow against the surface the earlier engines mapped, uses scout's fingerprints and CVE leads to focus where it matters, and streams confirmed findings into your Findings explorer.

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.

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.

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.

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.

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 (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.

Coming soon

On the roadmap, not yet available. These are in active development:

Extensions ecosystem & marketplace

Coming soon

An open marketplace of engines and integrations, built both by the Crossfyre team and the community. Discover, install and publish extensions that plug straight into your nodes and workflows, the same way the core mach / voyage / pulse engines do.

Valkyrie

Coming soon

An AI security agent that works alongside your scans: it gives intel and context on findings, and mutates vulnerability-scanning payloads to probe deeper and cut false positives. Not yet live.

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 [email protected]. Found a security issue? Email [email protected] privately (see the toolchain repo's SECURITY policy).