Umbra
← All docs

Binary-protocol testing via the agent (TCP)

Same relay as the HTTP leg, raw bytes. AI sends Postgres / MySQL / Redis / MongoDB / SSH wire-protocol packets through the agent into the customer network. Auth-method discovery, banner grabs, default-credential testing on internal databases, not just HTTP services.

Last updated May 28, 2026

What it is

The non-HTTP sibling of the AI exploit network leg. When the AI investigates an internal service the HTTP relay can’t help with (Postgres, MySQL, Redis, MongoDB, SSH banners, SMTP, FTP, etcd, Memcached, ICS/OT), the engine exposes a tcp() primitive that sends raw bytes to the target through the agent.

Mechanically: the cloud enqueues a proxy_tcp task in agent_tasks, the agent picks it up via its existing long-poll, opens a TCP socket on the target host:port (egress-locked to the authorised scope), optionally sends a payload, reads up to recv_max bytes, closes, and posts the bytes back. Cloud returns them to the AI to parse.

Send / recv go over the wire as base64 so binary protocols (PG handshakes with NUL bytes, Mongo BSON, SSH binary packets) round-trip through Postgres jsonb storage without loss.

What it produces

  • A proxy_tcp row in agent_tasks for every relayed round-trip, with target host:port / send bytes / recv bytes / elapsed_ms (durable, audit-queryable)
  • An audit_log entry tagged agent.proxy_tcp.create for every relayed call, with the run_id + actor user
  • Hex-dumped request/response in the run transcript so PoC display cites the exact bytes that proved the finding

What to use it for

  • Postgres / MySQL: send the startup packet, parse the AuthenticationRequest message. AuthenticationOK without a challenge → DB allows unauthenticated access (a real finding). MD5 / SCRAM → document the requirement.
  • Redis: PING, INFO, AUTH <password>. A +PONG response to PING without a -NOAUTH required identifies an unauthenticated instance.
  • MongoDB: isMaster / hello. If the DB answers without authentication, the whole instance is readable.
  • SSH: banner grab (SSH-2.0-OpenSSH_…) for version inference + supported auth methods, without ever attempting a credential.
  • SMTP / FTP / Memcached / etcd / Cassandra / ICS: same banner-grab pattern. Identifies versions + features for the CVE matcher.

A real example (PostgreSQL auth-method discovery)

From an actual run against an internal 127.0.0.1:5432:

  1. AI calls tcp(send=pg_ssl_request, recv_max=64), the 8-byte PG SSLRequest. Server replies with S (SSL supported).
  2. AI calls tcp(send=pg_startup_packet, recv_max=4096) with a minimal startup message (user=postgres, database=postgres). Server replies R 00 00 00 0c 00 00 00 05 <salt>, AuthenticationMD5Password with a fresh random salt.
  3. AI tries several user / database combinations. Every one returns an MD5 challenge with a different salt.
  4. Verdict clean: “PostgreSQL on port 5432 is network-reachable and responds to protocol-level probes; however, it is NOT openly accessible. MD5 password authentication is enforced for every user/database combination tested. SSL is also supported on the server.”

Without TCP relay this run would have been inconclusive. The AI would see the port open and have no way to test further. With TCP relay the verdict is substantive and the customer learns “my Postgres requires MD5 auth, no anonymous access”. Useful ground truth, not a maybe.

Why it matters

Most attack-surface tools test internal databases by either (a) running an on-prem scanner with bundled wire-protocol code (install friction, version drift, separate vendor for the AI layer) or (b) shipping CAP_NET_RAW privileges + raw scanners inside the agent (footgun, sysadmin pushback). Umbra does neither: the agent is one tiny static Go binary that does exactly one network operation per task type: TCP dial + send + recv. The protocol logic lives in the cloud’s AI engine where the model can adapt per-target.

Why it’s valuable

  • Egress-locked. Same model as the HTTP relay: the agent refuses any proxy_tcp to a host outside its CIDR allowlist. Cloud-side scope check is the first gate; the agent-side check is defence in depth above it.
  • One target per call. The send is dispatched to the target’s own host:port. No other destination is possible per call. Mirrors the lock on the HTTP relay.
  • Shared budget with HTTP. The AI’s per-run network call cap applies across both protocols, so a model can’t escape the rate limit by alternating http() and tcp().
  • Audit-replayable. Hex dumps of the send + recv bytes land in the run transcript, the proxy_tcp row, AND the audit_log. A customer can prove byte-for-byte what we sent on their behalf.
  • No new privileges on the agent host. Same Go net.Dial the discover-scan already uses: no CAP_NET_RAW, no root, no SUID, no syn-scan, no raw sockets.

Limits

  • One round-trip per call by design. The AI sends, the server replies once, the socket closes. Multi-step conversations on the same TCP session (e.g. PG password follow-up after the auth challenge) aren’t supported today. The AI can still test default credentials by opening a fresh socket per attempt for protocols that work that way (Redis AUTH, MongoDB SCRAM client-first), but full multi-round PG password testing needs session persistence we deliberately punted. Future work, additive.
  • Caps: 64K send, 256K recv, 30s timeout ceiling.

How to use it

Nothing to configure. Run any AI exploit against an internal service the agent discovered. If the target speaks HTTP the AI will use http_request; if it doesn’t, the AI will reach for tcp_send (or the python tool’s tcp() helper) automatically.

The transcript shows (via agent #N) next to every relayed TCP exchange, with the send + recv bytes hex-dumped, so the replay viewer is honest about how the request got there.