Menu

Star on GitHub · 3.1k

Vortex

CyberStrike's HTTP traffic engine: a deterministic analysis and replay engine that turns raw traffic into structured security intelligence, without an LLM in the loop.

Every request and response that CyberStrike sees, from a browser extension, a proxy, a crawler, or an agent's own replay, flows into one place: Vortex. It's the HTTP traffic engine at the core of the platform. Not a proxy. Not a scanner. A deterministic analysis and replay engine that turns raw traffic into structured security intelligence, without an LLM in the loop.

All traffic, one source: Vortex, one store, 700 deterministic rules

What it is

Vortex is a headless, embeddable TypeScript package (@cyberstrike-io/vortex). It ingests HTTP transactions, runs ~700 built-in rules over them, computes a cross-identity object/function graph, probes injection points, correlates multi-step chains, and exposes a governed replay engine, all deterministically. The AI agents that use it never see the internals. They get a narrow, typed facade: read leads, search traffic, inspect raw bytes, query the inventory, and send requests. Nothing else.

The rule engine

Vortex ships three rule shapes, all running through the same registry:

  • Per-transaction rules: fire on each individual request/response. Security headers, cookie flags, server banners, error signatures, technology fingerprints, misconfiguration patterns. ~700 built-in rules across 30+ categories: security, headers, auth, CDN, web servers, reverse proxies, JS frameworks, databases, CMS, containers, PaaS, development tools, CVE signatures, and more.
  • Corpus rules: fire across the entire traffic corpus. Cross-identity access control (endpoint reachable under identity A and B), unauthenticated reach (endpoint accessed with and without auth), auth-strip differential (same request with and without credentials). These are the pentest core: they answer questions that a single-request scanner can't even ask.
  • Declarative rules: LLM-friendly JSON. A rule is data, not code:{"id": "sql-error", "when": "regex('SQL syntax', resp.body)", "severity": "high"}. The DSL expression engine (below) powers the when clause. Agents can author and emit them.

All rules produce Signals: deduplicated, categorized, severity-tagged findings. A signal carries a dedupKey so the same finding on the same logical endpoint collapses to one, not one per request.

The DSL

Vortex has its own expression language: a small, safe predicate DSL with a function library over the transaction model. It subsumes HTTPQL (the agent query interface) and powers rule conditions, chain links, and probe matchers.

resp.status == 500 && regex("SQLSTATE", resp.body)
compare_versions(resp.header.server, "< 2.4.50")
contains(base64_decode(jwt_payload(req.header.authorization)), "\"alg\":\"none\"")

Functions include: regex, contains, starts_with,ends_with, len, split, base64_decode,base64_encode, url_decode, url_encode,md5, sha256, jwt_payload,compare_versions, to_lower, to_upper, and more. Two consumers, one engine: agents get the query surface (grep-gated, safe); rules get the full scope.

Inventory: the object/function graph

For every transaction, Vortex extracts subjects: which data objects were touched (order:42, user:7), which function was called (GET /api/orders/{id}), under which identity/role, and how that role reached it ("crawl" = organic navigation vs "forced" = replay only).

These aggregate into an Inventory, the cross-identity graph:

  • ObjectRecord: one per unique data object. Carries which roles accessed it, through which endpoints, in which sites (path/query/body/header), and which fields are sensitive or id-shaped. An object reached under more than one role is anIDOR/BOLA candidate.
  • FunctionRecord: one per endpoint. Carries which roles called it, with provenance. A function called by more than one role where one role's provenance is "forced" is a BFLA surface.

This is deterministic access-control lead generation. No LLM guessing which endpoints to test: the inventory says exactly which objects and functions are cross-role, with the transactions to replay.

Injection probing

Vortex enumerates every input parameter in the corpus, query, body (nested/array dotpaths), id-shaped path segments, injectable headers, as inject points. For each point, the prober fires a payload battery per injection class and detects hits:

  • Reflected: a canary token bounced back in the response (XSS lead)
  • Evaluated: a template canary's product surfaced, e.g. "49" from {{7*7}} (SSTI)
  • Error: a DBMS/interpreter error signature appeared that wasn't in the baseline (SQLi)
  • Redirect: the response Location points at the injected canary host (open redirect)
  • Header-inject: an injected header surfaced in response headers (CRLF injection)
  • Time: the probe response was significantly slower than baseline (blind command injection)

Each inject point carries a coverage ledger, which classes were tested, with what result, so the agent knows exactly what's been probed and what hasn't.

Canary correlation

A canary is a unique alphanumeric token embedded in a request. Vortex scans everysubsequent observed response for it. Same-request reflection is ordinary (XSS). Cross-request reflection, a token injected at endpoint A that surfaces in a different response B, is stored/second-order injection, the hardest case to catch. Vortex tracks it automatically, classifying the reflection context (HTML text, attribute, script, comment) so the follow-up knows which breakout to attempt.

It sees every request: Vortex, the deterministic engine

The send engine

Vortex includes a full governed HTTP replay engine:

  • Mutate: field-level request mutation (method, target, query params, headers, body fields). Pure clone-and-modify: a battery of variants derived from one base without cross-contamination. Values are raw, encoding is explicit.
  • Encode: 11 composable codecs (URL, URL-all, double-URL, base64, base64url, hex, HTML decimal/hex entities, unicode escapes, upper/lower). Chain them for WAF bypass testing: ["base64", "url"] wraps a base64 blob in URL-encoding.
  • Govern: four safety primitives protect both the target and the platform:
    • Global budget: hard cap on total requests per session (default 5,000)
    • Circuit breaker: per-host, opens after consecutive failures, auto-recovers
    • AIMD limiter: additive-increase / multiplicative-decrease concurrency control
    • Retry: transient and idempotent only, never retries timeouts (could be time-based evidence)
  • Replay safety: refuses to replay requests that would destroy the live session (single-use OAuth codes, PKCE verifiers, refresh tokens, session-minting endpoints). Identifies the single-use tokens so the caller can substitute fresh values instead.

Chain rules

Multi-step vulnerabilities need correlation across transactions. A chain rule is an ordered list of steps, each a DSL expression over its own transaction, joined bylink fields or reuses (value-based correlation: a correlatable token from response A that appears in request B, regardless of field name). Deterministic nested join over the corpus, bounded to prevent blowup.

{
  "id": "reset-token-leak-reuse",
  "steps": [
    { "as": "leak", "when": "resp.body.reset_token" },
    { "as": "use",  "when": "resp.status == 200",
      "link": [{ "field": "req.query.token", "to": "leak.resp.body.reset_token" }] }
  ]
}

Discovery

Extractors (like the JS bundle miner) pull endpoints, JS URLs, technology markers, and secrets out of observed traffic. Vortex stores them as Discovered items, attack surface the crawl or the agents haven't hit yet. Each item tracks whether it's been exercised (hit) and how the page loaded it (executed/loaded/preloaded/referenced), so a finding on a JS asset the app ships but never actually runs can be down-ranked.

Value correlation (taint)

When a token-like value appears in response A and later in request B, that's dataflow, regardless of field names. Vortex's taint module extracts correlatable values from both sides (length at least 8, alphanumeric, sufficient entropy) and intersects them. ThewhereValue pivot lets an agent trace where any spotted value flows across the entire corpus.

The agent facade

Agents never import the store, rule engine, or send internals directly. They get aVortex facade with exactly these capabilities: leads,inspect, search, objects, functions,crossRole, whereValue, untested,injectPoints, probe, and send. The facade is framework-agnostic: CyberStrike adapts it to its tool framework; an MCP server or any other consumer does the same with a ~10-line adapter.

Rule packs

For scale (~20k rules), Vortex supports file-distributed rule packs: YAML/JSON files loaded from directories, selected by tags/severity/category plus detected tech stack, compiled only when selected. The selectRules function takes a context (detected technologies, target scope) and returns only the rules that apply, so a WordPress target gets WordPress rules, not the full 20k set.

Package @cyberstrike-io/vortex · TypeScript/Bun · AGPL-3.0-only. Zero external runtime dependencies. Embeddable in any Node/Bun host.

Was this article helpful?