agentcensus

The connector

A container you run inside your own network to inventory the AI agents and MCP servers running there. It is read-only by default: verification only when you enable it, only against targets you nominated, defined in a config only you control. This page is what you are being asked to approve: what it does, what it cannot do, how to check the image is ours, and what we commit to as its supplier.

Generated from the source document, so this page and the one we work from are the same text. Contact security@agentcensus.io.

Status: Approved with the ADR-029 amendments of 2026-08-17 and 2026-08-25 (the opt-in verify mode, tier 1) · Owner: Ingmar · Deputy: Nic · Contact: security@agentcensus.io · Review by: 2026-11-20 (first publish, 2026-08-22, + 90 days)

Written for the security team being asked to approve the connector, and kept short enough to be read by one. Every statement here is either enforced by the platform or has a named person behind it; where it is neither, it says so.

The commitments below are the ones that attach to the first signed image and to every one after it. This file is the source of the public page at /connector, which is generated from it at build — there is no second authored copy, so what you read here and what you read there are the same text, and the connector's own README.md is rendered onto the end of it.

Until the first image has been published there is nothing to pull. The release list at /connector/releases.json is the answer to whether that has happened: it names every version that exists, its digest, and whether it has been withdrawn. An empty list means nothing has been published yet.


1. What you are being asked to run

An egress-only container that runs inside your network, and is read-only by default: verification only when you enable it, only against targets you nominated, defined in a config only you control. It reads the hosts your own administrator listed in its configuration file — explicit hosts, never address ranges, and it derives no new hosts from what it finds — and on each of them issues GET requests for a small set of agent-discovery documents: the well-known paths for agent cards, catalogues and indexes, /openapi.json, and /.well-known/mcp.json. It reads JSON up to 1 MiB and ignores everything else. Once per run it makes one outbound HTTPS POST to the platform URL in its configuration, authenticated with a credential it holds for itself alone.

Verification is off unless your configuration file has a verify block, and a file without one runs the connector exactly as described above. Each entry in that block names one of the hosts you already listed, one endpoint path on it, and the protocol it speaks. For those endpoints only, the connector sends the read-only first-tier checks, without a credential: the MCP initialize handshake and its tools/list, resources/list and prompts/list calls, or the A2A capabilities read. These are protocol requests rather than document reads, and some are sent as POST, because that is how the protocol asks. The results go to your organisation's private store, marked as observed from inside your network, in a second outbound POST to the platform per run. They are never written to the public census and never used in a score.

What it cannot do: it accepts no inbound connection and holds no port open; it takes no command from us, because its behaviour is fixed by the local configuration file you provide and there is no channel by which we — or anyone who compromised us — could turn verification on, add an endpoint to it, or tell it to do anything else; it never invokes a tool or submits a task, with or without verification, and being inside your network changes nothing about that; and it cannot read your data back out, because its credential authorises submission and resolves to no read scope at all.

The detailed statement is services/cmd/connector/README.md (What it does / What it cannot do), rendered into the same public page as this one.

2. Where it comes from, and how to check it

Nothing is rebuilt at publish time. The image promoted to the public registry is the digest CI built and scanned; the digest you verify is that digest.

3. Reporting a vulnerability

Mail security@agentcensus.io. It is a forwarding mailbox that reaches a person, not a queue (SECURITY.md, ADR-016), and a report is acknowledged within 2 business days. Do not open a public issue; the repository is private and a public report would be a disclosure.

Include what you observed, which version and digest you were running, and how to reproduce it. What happens next: we triage, tell you what we found, and ship a patched release under the timescale in §6. The finding is disclosed on /connector once the fix is available, or after 90 days, whichever comes first, and we will name you if you want to be named.

There is no bug bounty. We would rather say so than let you find out after the work.

4. Support window

The current minor and the previous minor are supported. A minor that is superseded stays supported for 90 days after its successor ships.

While the connector is on 0.x, a minor release may change the wire contract, so the window is also a compatibility commitment: /api/v1/connectors/enroll, /api/v1/connectors/reports and /api/v1/connectors/verifications keep accepting a supported version's requests for as long as it is supported. "Supported" means that, plus security fixes. It does not mean new features.

What happens outside the window. The connector identifies itself as User-Agent: agentcensus-connector/<sha> — the commit SHA is the only version the binary knows. The API resolves that SHA to its published version, records both against the connector, and the console shows the version with "update available". Past the window, every submission is answered with a warning for 30 days, and then refused with 426 connector_version_unsupported.

Refusal is the only lever we have, and it is worth being plain about what it does: we cannot reach into your network and change the binary, so the only thing we can stop is the data arriving. The connector keeps running; its reports stop being accepted.

5. Update path

There is no automatic update, and there will not be one. An updater is a command channel with a friendlier name, and the connector is scoped to have no command channel (ADR-029 §3).

How you find out a release exists: /connector and its releases.json, which carry each version's digest and verify command; a line in the connector's own log on start; and the console.

How you update: pull the new tag and restart the container. The enrolled credential and your configuration file carry over — you do not re-enroll, and the join token is not needed again. Compatibility across an update inside the support window is the commitment in §4.

6. Vulnerabilities in what we ship

The SBOM is watched by two things: govulncheck weekly, which is reachability-aware, and ECR image scanning on the private build repository — the same digest as the public copy, so a finding on one is a finding on both.

A critical or high finding that is reachable from the connector's own code paths gets a patched release within 14 days of an upstream fix being available. A finding that is not reachable is recorded on the release page and is not patched on demand; shipping a release to change a scanner's output is churn, not security. "Reachable" means govulncheck reports a call path to the vulnerable symbol, or the finding is in the base image on a path the binary uses; where the tooling is ambiguous, the owner named at the top of this page decides and the decision is recorded with the release.

7. Withdrawing a release

A published, signed image cannot be unpublished quietly, and we will not pretend otherwise by trying. A withdrawn version is marked as withdrawn on /connector with the reason and the replacement to move to; its User-Agent is refused at /api/v1/connectors/reports and /api/v1/connectors/verifications from that day; and if the reason is a vulnerability, it is mailed to the security@ notification list. The tag and the signature stay where they are. The page says why nobody should run it.

8. What we will not promise

9. Enrollment and revocation

10. Owner and review

Owner Ingmar
Deputy Nic
Contact security@agentcensus.io
Review this page is re-read and re-dated every 90 days, and on any change to §4 or §6
security@ reaches a person last verified 2026-09-02, by Ingmar

The mailbox check is a test message answered by a human, done before the first image is published and at every review since. A contact address nobody has sent mail to is a promise nobody has tested.

The 2026-09-02 entry is that test, and it was the first message this address had ever received — the mail bucket's inbound prefix had two objects before it, both from 2026-08-09 and both to abuse@. SES accepted it with spam, virus, SPF, DKIM and DMARC all PASS, archived it, and darknetian-mail-forwarder forwarded it to the owner's mailbox. So the routing half of this row is measured rather than asserted, and the log is in /aws/lambda/darknetian-mail-forwarder. The half no log can show is the answer, which is why the row names a person and not a pipeline.


What it reads, what it sends, and what it never does

A container you run inside your own network to find the AI agents and MCP servers running there, and report them — privately, to your organisation on agentcensus — so you have the same inventory of your internal agents that the public census gives you for the internet.

What it finds is private to your organisation. It never enters the public census, and the platform operator sees only aggregate counts, never the details, unless you approve a specific, time-boxed, revocable access request (ADR-029).

It is read-only by default: verification only when you enable it, only against targets you nominated, defined in a config only you control.

This document is written for the security team being asked to approve it. It describes exactly what the connector does, and — more importantly — what it cannot do.

What it does

What it cannot do

The three commands

Command What it does
enroll --token <join token> --platform <https://…> Exchanges a single-use join token, once, for this connector's own credential; writes it to the state directory; exits.
run [--config FILE] [--state DIR] The default. Reads the credential from state and the targets from config, discovers, submits.
version Prints the commit the binary was built at.

An admin in your organisation mints the join token in the console. It is single-use and valid for 15 minutes, and it is spent the moment the connector exchanges it. Supply it as --token, or as CONNECTOR_JOIN_TOKEN in the environment — never in the config file, which holds nothing secret and can be checked into your own configuration management as it is.

If run finds no stored credential and CONNECTOR_JOIN_TOKEN is set, it enrols first. That is the Kubernetes case: a Secret mounted as an environment variable and no init container.

Revocation

You can see every enrolled connector in the console — where it enrolled from and when it last reported — and revoke any of them instantly. A revoked connector stops being able to submit on its next request. Revoking deletes nothing, on purpose: losing a credential should not lose your inventory.

Configuration

A local JSON file (--config, default /etc/connector/config.json). Unknown fields are refused, so a misconfigured connector fails to start rather than running with a silently dropped setting. See config.example.json.

Nothing in it is secret. The join token and the credential's location both left this file deliberately: a bearer credential parked in a config file with a manual "remember to delete this" step is weaker than one that is consumed.

Field Meaning
platform_url Where reports are submitted. Must be https.
targets The exact https://host[:port] targets to read. Explicit hosts only — no ranges, no paths.
well_known_paths Which documents to read (defaults to the agent-discovery set above).
interval_hours Re-discover every N hours. 0 (default) runs once and exits.
verify Optional, and absent by default. The endpoints to verify; see below.

Verification (off unless you turn it on)

Discovery reads the documents an agent publishes. Verification checks that the endpoint a document names answers the way the document says it does. It runs only when the config has a verify block:

"verify": [
  { "target": "https://billing.corp.internal", "endpoint_path": "/mcp",
    "protocol": "mcp", "tiers": ["tier1"] }
]

What it records for each call is the outcome, the status, timings, the certificate's expiry, the negotiated version, the names of the capabilities the endpoint listed, and whether it refused an unauthenticated caller. It records no tool output, because it calls no tool. The results go to your organisation's private store, marked as observed from inside your network. They never reach the public census or a published figure, and they are never used in a score.

Only this file turns verification on. The platform cannot turn it on, add an endpoint to it, or widen a tier, because there is no channel for it to do so.

Running it

# Once, with the token from the console.
docker run --rm \
  -v agentcensus-connector:/etc/connector/state \
  <image> enroll --token <join token> --platform https://agentcensus.io

# Then, on a schedule or as a long-running container.
docker run --rm \
  -v /etc/connector:/etc/connector:ro \
  -v agentcensus-connector:/etc/connector/state \
  <image> run

Two mounts, and the split matters: the config mount is read-only and the state directory is not. The connector writes exactly one file, its credential, into /etc/connector/state. Mounting that path read-only makes enrollment fail — and the connector now says so and refuses before it spends your join token, rather than after.

It needs egress to the targets you nominated and to platform_url, and nothing else.

Versions and support

The binary knows one thing about itself: the commit it was built at, which is what version prints and what its User-Agent carries. The release it was published as is the image tag, and the platform resolves the commit to that version from the published release list — so the console can tell you which release you are running and whether a newer one exists.

The support window, the vulnerability contact, how to verify the image, and what happens to a version that falls out of the window are all in the supplier commitments, published at /connector.