Skip to content

nuclide-research/visorbait

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

visorbait

Canonical honeypot intelligence for AI/ML infrastructure scanners.

release license go NuClide

FeaturesInstallationUseClassifierPython bridgeScope


visorbait is a Go CLI and shared signature database for known honeypot fleets. Subscriber model: maintain one signature DB so every recon tool can filter bait responses before promoting them to a "verified unauth" finding. Saves every operator from re-discovering the same fleets one platform sweep at a time.

The inverse of VirusTotal. Instead of "is this thing malware?" the question is "is this thing fake infrastructure pretending to be the platform I am scanning for?" Part of the NuClide Visor* tool lineup (VisorRoam, VisorCAS, VisorLog, VisorGraph, VisorPlus, VisorScuba, VisorAgent).

Features

  • Shared honeypot-fleet signature database, embedded in the binary
  • AS63949 (Akamai/Linode/Aliyun residential) fleet seeded by default: shared crypt salt wW0sffoqsk.EM, three reusable bait markers
  • Four-signal classifier: body hash, IP list, marker-substring co-occurrence, ASN match
  • Per-classification confidence (high, medium, low) with the matched reasons inline
  • Exit code 0 on honeypot match, 1 on clean. Pipeline-composable
  • classify (from body or stdin), check (live single-GET URL), seed (add a fleet), list (inspect DB)
  • User-local DB at ~/.visorbait/fleets.json shadows the embedded one. Edit it directly to add ASN ranges, IP lists, hashes
  • Python bridge (bridge.py) for scanners that want to call out via subprocess

Installation

Requires Go 1.22+.

go install -v github.com/nuclide-research/visorbait@latest

Or build from source:

git clone https://github.com/nuclide-research/visorbait ~/visorbait
cd ~/visorbait && go build -o visorbait .

Use

Classify a body

$ cat suspicious-response.json | visorbait classify --body-file -
HONEYPOT AS63949 [medium]  reasons: markers=3/3

$ visorbait classify --body-file body.txt --asn AS63949 --json
{"fleet":"AS63949","confidence":"high","reasons":["markers=3/3","asn-match"]}

Exit code is 0 on match, 1 on no-match. Compose with shell:

if visorbait classify --body-file body.txt > /dev/null; then
  echo "skip: honeypot"
fi

Check a live URL (single GET)

$ visorbait check --url http://198.51.100.42:12207/api/version
http://198.51.100.42:12207/api/version -> 200  HONEYPOT AS63949 [medium]
  reasons: markers=3/3

Inspect the signature DB

$ visorbait list
visorbait DB version=0.1 updated=2026-06-07  1 fleet(s)

  AS63949
    Akamai/Linode/Aliyun residential-range honeypot fleet. Emits identical
    bait JSON containing the shared crypt salt 'wW0sffoqsk.EM' and a
    'VULNERABLE -version' marker across many probe endpoints.
    markers=3  body_hashes=0  ips=0  asns=1

Seed a new fleet

$ visorbait seed --name FOO-FLEET --body-file captured-bait.txt \
                 --markers "honeypot-string-1,honeypot-string-2" \
                 --desc "Found during MLflow sweep, 2026-XX-XX" \
                 --source "your-handle"
seeded FOO-FLEET (hash=...) into ~/.visorbait/fleets.json

Classifier model

A body is classified as a honeypot when any of:

Signal Confidence
Body sha256 exact-matches a known bait hash high
Candidate IP is in a known honeypot IP list high
2+ marker substrings co-occur in the body medium
Candidate ASN matches a fleet ASN (no body signal) low

Falsifiability: a clean body returns null. The exit code lets shell scripts gate on match status.

Integration: Python bridge

Scanners written in Python can call visorbait via subprocess:

import subprocess, json

def is_honeypot(body: str, ip: str = "", asn: str = "") -> dict | None:
    p = subprocess.run(
        ["visorbait", "classify", "--body-file", "-",
         "--ip", ip, "--asn", asn, "--json"],
        input=body, capture_output=True, text=True, timeout=5,
    )
    if p.returncode == 1:
        return None
    return json.loads(p.stdout)

See bridge.py for the canonical helper.

Contributing a fleet signature

If you encounter a honeypot fleet in your own sweeps:

  1. Capture a representative bait body (curl -sk URL > captured.txt)
  2. Identify the markers: substrings that distinguish the family from legitimate responses (shared salt, fake credential lines, signature error strings, distinctive port distribution)
  3. visorbait seed --name <FLEET-NAME> --body-file captured.txt --markers "..."
  4. Submit a PR with the updated data/fleets.json

Why this exists

During a NuClide sweep of Ray Dashboards, all seven "open Ray Dashboard" candidates that responded turned out to be honeypots from the AS63949 fleet, the same fleet documented in prior NuClide research. Without a shared filter, every scanner re-learns the fleet from scratch and risks notifying the wrong abuse contact. Codifying honeypot signatures keeps the verified-finding ledger honest.

Scope

visorbait classifies HTTP response bodies and live URLs against an embedded honeypot signature DB. check makes one HTTP GET per URL. classify makes zero network calls. seed writes to the user-local DB at ~/.visorbait/fleets.json. No authentication, no POSTs, no exploits. Only point check at hosts you own or have explicit written authorization to assess.

Our other projects

  • aimap — AI/ML infrastructure fingerprint scanner
  • scanner — active-banner stage between passive discovery and deep enumeration
  • VisorLog — finding ledger and ingest pipeline
  • VisorCAS — content-addressed false-positive ledger
  • VisorGraph — cert-pivot to operator attribution

License

MIT. Part of the NuClide toolchain. Contact: nuclide-research.com

Releases

No releases published

Packages

 
 
 

Contributors