268,000 Exposed AI Systems: What Censys Found in Nine Months

·9 min read·Evergreen Tools Team

Censys published its fifth annual State of the Internet Report on October 14, 2026, and the headline number is a growth rate rather than a breach: internet-facing AI tools grew 63% in nine months, reaching nearly 268,000 systems. That count is wider than chatbots. It includes the software that connects models to data, applications and user accounts, which is exactly the layer most teams stood up quickly and documented least. Here is what the report measured, which findings change a decision you are about to make, and the parts you can verify on your own infrastructure this week.

Rack servers in a data centre

Internet-facing AI tools grew 63% in nine months, reaching nearly 268,000 systems

What the report actually measured

The Censys Advanced Research Collective analysed historical and real-time data from the Censys Internet Map, which continuously monitors global internet infrastructure, and published the results on October 14. The finding that gets quoted is a 63% increase in internet-facing AI tools over nine months, taking the total to nearly 268,000 systems. Censys is explicit that this is not just chat interfaces: it covers the behind-the-scenes tooling that connects AI to data, applications and user accounts. Chief executive Zakir Durumeric frames the point as new technologies introducing new layers of infrastructure, and continuous monitoring being what lets you use them without inheriting unmanaged risk. The useful reading is that growth like this outruns documentation, not that any particular product is broken.

# Run this from OUTSIDE your network, and only against hosts you own.
import urllib.request

MY_HOSTS = ["flow.example.com", "agent.example.com"]

SIGNATURES = {
    "n8n editor login": "/rest/login",
    "n8n public API": "/api/v1/workflows",
    "agent console": "/__console",
}

def probe(host, path, timeout=5):
    url = "https://" + host + path
    try:
        with urllib.request.urlopen(url, timeout=timeout) as resp:
            return resp.status, resp.read(200).decode("utf-8", "ignore")[:80]
    except Exception as exc:
        return None, type(exc).__name__

for host in MY_HOSTS:
    for label, path in SIGNATURES.items():
        status, info = probe(host, path)
        if status and status < 400:
            print(host, "|", label, "answers", status, "from the public internet")

# Censys is scanning these hosts whether or not you are. The only question
# is whether your inventory agrees with what an outsider can see.

n8n is the largest exposed AI product on the internet

Nearly 114,000 hosts running n8n are reachable from the public internet, which makes the workflow automation platform the most widely exposed AI product in the dataset by a wide margin. Agent console OpenClaw follows at roughly 54,000 hosts. Three countries account for just over half of all exposed AI infrastructure: the United States at 62,687 hosts, China at 42,511 and Germany at 31,222. The reason n8n dominates is structural rather than careless. It is self-hosted by default, it ships a web editor, and it receives webhooks, so somebody at some point exposed it on purpose to let an outside service call it. The part that rarely gets reassessed afterwards is everything the workflow can reach: credentials for every connected service, plus whatever the workflow is allowed to write.

# The automation tool is the one to check first: nearly 114,000 hosts in the report.
# Read the running container's effective config instead of trusting the .env file.
import json, subprocess

def n8n_env(container="n8n"):
    raw = subprocess.run(["docker", "inspect", container, "--format", "{{json .Config.Env}}"],
                         capture_output=True, text=True, check=True).stdout
    return dict(kv.split("=", 1) for kv in json.loads(raw) if "=" in kv)

env = n8n_env()
CHECKS = {
    "bind to loopback or an internal interface": env.get("N8N_LISTEN_ADDRESS", "0.0.0.0") != "0.0.0.0",
    "public API disabled unless used": env.get("N8N_PUBLIC_API_DISABLED", "false") == "true",
    "owner account set up": bool(env.get("N8N_USER_MANAGEMENT_DISABLED", "") == "false"),
    "encryption key pinned, not generated": bool(env.get("N8N_ENCRYPTION_KEY")),
    "external URL reflects the real host": bool(env.get("WEBHOOK_URL")),
}
for name, ok in CHECKS.items():
    print(("PASS  " if ok else "CHECK ") + name)

# Every failed line is a host an attacker can reach and you cannot explain.
Streams of security code on a screen

Among the exposed systems, workflow automation is the quietest and the largest group

134,000 exposed industrial hosts, mostly on consumer networks

The report identified roughly 134,000 internet-exposed hosts running industrial control systems, and about 70% of them are found on consumer and mobile networks. That distribution is what makes the number hard to act on: an ICS device behind a home or mobile connection does not map cleanly to an owner, a maintenance window, or a security team. Regionally, North America holds about 38% of exposed ICS, Europe 32% and Asia 25%. The practical question for anyone with operational technology is narrower than the headline: is any of it reachable from the internet, and is the network path the one you believe it is. Fragmented ownership is the reason these exposures persist, and the reason a single scan is not enough.

# An exposure ledger is only useful if it is a file with owners, not a wiki page.
import yaml

LEDGER = (
    "services:\n"
    "  - name: n8n-flow\n"
    "    host: flow.example.com\n"
    "    public: true\n"
    "    auth: owner-account + 2FA\n"
    "    network_path: cloudflare-tunnel\n"
    "    update_channel: monthly\n"
    "    owner: platform-team\n"
    "    reviewed: 2026-10-16\n"
    "  - name: agent-console\n"
    "    host: agent.example.com\n"
    "    public: true\n"
    "    auth: null\n"
    "    network_path: cloudflare-tunnel\n"
    "    update_channel: null\n"
    "    owner: null\n"
    "    reviewed: 2026-09-02\n"
)

def audit(entry, today="2026-10-16"):
    problems = []
    if entry["public"] and not entry["auth"]:
        problems.append("public with no auth")
    if entry["public"] and entry["network_path"] == "direct":
        problems.append("public, directly addressed")
    if not entry["owner"]:
        problems.append("no owner")
    if not entry["update_channel"]:
        problems.append("no update channel")
    return problems

doc = yaml.safe_load(LEDGER)
for svc in doc["services"]:
    issues = audit(svc)
    print(svc["name"], "->", issues or "clean")

# A service with no owner and no update channel is the shape of every long-lived exposure.

Threat infrastructure is not distributed evenly

Censys splits observed threat infrastructure into host-level and web-based categories, and the geography flips between them. China hosts 36.6% of malicious host-level infrastructure such as command-and-control servers and remote access tooling, against 16.8% for the United States. For web-based threats such as phishing and deceptive pages, the United States hosts 45.5% and China 20.9%. The split matters because the two halves need different defences. Host-level infrastructure shows up in your egress traffic and DNS, where filtering and monitoring help. Web-based threats arrive at people, where the controls are URL reputation, mail filtering and user-facing warnings. Reading one number as the whole picture leads to protecting the wrong side of the connection.

# Industrial protocols have no business being reachable from a consumer network.
# Check your own ranges only: Modbus 502, S7comm 102, EtherNet/IP 44818.
import ipaddress, socket

MY_RANGES = ["10.20.0.0/24"]
INDUSTRIAL = {502: "Modbus", 102: "S7comm", 44818: "EtherNet/IP"}

def reachable(ip, port, timeout=1.5):
    with socket.socket() as sock:
        sock.settimeout(timeout)
        return sock.connect_ex((str(ip), port)) == 0

for cidr in MY_RANGES:
    for ip in ipaddress.ip_network(cidr).hosts():
        for port, name in INDUSTRIAL.items():
            if reachable(ip, port):
                print("exposed upstream:", ip, name, port)

# The report counted roughly 134,000 internet-facing ICS hosts.
# About 70% of them sit on consumer and mobile networks, which is why nobody can name an owner.
A network of connected nodes

An outside-in inventory comes before hardening

Median patching improves while the oldest versions linger

The report also tracked adoption across four products: Progress Telerik Report Server, Jenkins, Cleo MFT and Microsoft SharePoint Server. Organisations did move to newer versions over the study period, but the oldest versions in each population remained largely unchanged. That combination is common and easy to misread. Aggregate or median patch level improves while the small group that generates most incidents does not move at all, because upgrading the majority is cheap and upgrading the tail is expensive — somebody has to test it, and there is always a reason not to. If you only report an average, the tail is invisible in exactly the reporting that is supposed to surface it.

# Median patch level improves. The oldest version in the fleet does not.
# Track the tail, because that is the one that gets exploited.
from collections import Counter

INVENTORY = [
    {"product": "jenkins", "host": "ci-1", "version": "2.492"},
    {"product": "jenkins", "host": "ci-2", "version": "2.375"},
    {"product": "sharepoint", "host": "intranet", "version": "16.0.10417"},
    {"product": "telerik-report-server", "host": "reports", "version": "10.1.24.514"},
]

FLOOR = {"jenkins": "2.440", "sharepoint": "16.0.10400", "telerik-report-server": "10.1.24.514"}

def parse(v):
    return tuple(int(p) for p in v.replace("-", ".").split(".") if p.isdigit())

def drift(rows):
    out = []
    for row in rows:
        below = parse(row["version"]) < parse(FLOOR[row["product"]])
        out.append((row["host"], row["product"], row["version"], "BELOW FLOOR" if below else "ok"))
    return out

for line in drift(INVENTORY):
    print(line)

print("version spread:", Counter(r["version"] for r in INVENTORY))

# Censys studied Telerik Report Server, Jenkins, Cleo MFT and SharePoint:
# organisations moved to newer releases, the oldest ones stayed put.

A four-step order for this week

Start from the outside, not from your service catalogue, because the catalogue is the thing being tested and it will disagree with reality. Then put two things in front of every genuinely public service: authentication that a person owns, and a network path such as an authenticated tunnel rather than a direct address. Then pin a supported version floor per product and report drift against the floor instead of an average. Finally, put a date on the ledger and re-run the whole check monthly, because these numbers move: the AI layer in this report grew 63% in nine months, and your inventory did not grow that slowly. Everything above fits in a single review meeting if the list is short and the owners are named.

📌 Frequently Asked Questions

What did the Censys 2026 State of the Internet Report find?

Internet-facing AI tools grew 63% in nine months to nearly 268,000 systems. n8n was the most widely exposed AI product at nearly 114,000 hosts, followed by OpenClaw at roughly 54,000. The report also counted about 134,000 internet-exposed industrial control hosts, roughly 70% of them on consumer and mobile networks.

Does exposing n8n mean I have been compromised?

No, exposure is not the same as a breach. It means the editor or API is reachable from the public internet, so authentication and network path are now the only things standing between an outsider and the credentials your workflows hold. Treat it as an inventory and access question first.

Which countries host the most exposed AI infrastructure?

Per Censys, the United States at 62,687 hosts, China at 42,511 and Germany at 31,222 together account for just over half of all exposed AI infrastructure.

Why do the exposed industrial control hosts matter?

Because roughly 70% of them sit on consumer and mobile networks, so ownership is hard to establish and remediation has no obvious owner. Regionally, North America holds about 38% of the exposed total, Europe 32% and Asia 25%.

How often should I re-check my own exposure?

Monthly is a reasonable floor, and any time you add a self-hosted service, change a tunnel or webhook route, or rotate credentials. The lesson of a 63% nine-month growth rate is that the environment changes faster than a yearly review cycle.