Inspect incoming agents experimental · 0.x
@nessgate/inspect describes what an incoming automated caller claims and what can actually be verified. It reports evidence only — no scores, no allow/deny, no identity guarantees.
@nessgate/inspect evaluates requests where it is running, so to inspect
traffic on your domain, run it in your own request-handling layer — where the source IP,
headers, and any signatures are available.
Run it locally
Install the package:
npm i @nessgate/inspect
A tiny server that reports evidence about each request it receives:
// inspect-server.mjs
import { createServer } from "node:http";
import { inspect } from "@nessgate/inspect";
createServer(async (req, res) => {
const headers = Object.fromEntries(Object.entries(req.headers));
const request = { method: req.method, url: `http://${headers.host}${req.url}`, headers };
const evidence = await inspect(request, { sourceIp: req.socket.remoteAddress }); // the real connection peer
res.writeHead(200, { "content-type": "application/json" });
res.end(JSON.stringify(evidence, null, 2));
}).listen(8799);
Start it, then send it a request:
node inspect-server.mjs curl -s localhost:8799/ -H 'user-agent: Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot)'
Already using Express? Two lines — every handler then has req.nessgate:
import { nessgateInspect } from "@nessgate/inspect/middleware";
app.use(nessgateInspect());
X-Forwarded-For.A request from your own machine or a cloud function will show claimed (and directory-attributed if you send a known bot User-Agent). The stronger tiers appear only for genuine operator traffic or a signed request — that is the correct, honest result.
Evidence levels
Every fact is placed in exactly one tier and carries provenance. The examples below are real output from the package, labelled with the exact input that produced each one.
claimed User-Agent
The caller's User-Agent, asserted in a request header. It is trivially spoofable and bound to nothing, so on its own it is not evidence of identity.
Worked example — input: a request with User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36.
{
"kind": "user-agent",
"tier": "claimed",
"statement": "the caller's User-Agent is \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36\"",
"value": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
"provenance": [
{
"source": "request-header",
"header": "user-agent"
}
],
"note": "a request header asserted by the caller; trivially spoofable and bound to nothing — not evidence of identity on its own."
}
directory-attributed public attribution
The declared User-Agent matches a published operator pattern (here, OpenAI's GPTBot). This shows the string is a recognized pattern; it does not bind this request to that operator, because the header can be spoofed.
Worked example — input: a request with User-Agent: Mozilla/5.0 (compatible; GPTBot/1.2; +https://openai.com/gptbot).
{
"kind": "public-attribution",
"tier": "directory-attributed",
"statement": "the declared User-Agent matches a published pattern operated by OpenAI",
"operator": "OpenAI",
"provenance": [
{
"source": "request-header",
"header": "user-agent"
},
{
"source": "public-agent-directory",
"pattern": "GPTBot",
"documentation": "https://platform.openai.com/docs/bots"
}
],
"note": "attribution of a self-declared, spoofable string against a public directory — it does NOT bind this request to that operator. Corroborate with a verified signature or verified reverse-DNS for binding."
}
network-verified origin infrastructure
The connection matches the operator's published network-verification method (here, Google's reverse-DNS forward-confirmation) and supports attribution to its documented infrastructure. It does not establish trust, authorization, or safety.
Worked example — input: a request whose source IP 66.249.66.1 reverse-resolves to a Google crawler host and forward-confirms, as Google's documented method requires. Methods are wired today for Google, Bing, Apple, OpenAI and Perplexity.
{
"kind": "network-attribution",
"tier": "network-verified",
"statement": "the source IP 66.249.66.1 is within infrastructure Google officially attributes to its bot (method: rdns-forward-confirm)",
"operator": "Google",
"method": "rdns-forward-confirm",
"provenance": [
{
"source": "connection",
"sourceIp": "66.249.66.1",
"note": "the real connection peer; forwarded headers were NOT trusted"
},
{
"source": "reverse-dns-forward-confirmed",
"hostname": "crawl-66-249-66-1.googlebot.com",
"documentation": "https://developers.google.com/search/docs/crawling-indexing/verifying-googlebot"
}
],
"note": "means ONLY that this request originated from Google's documented infrastructure — it does NOT mean the caller is trusted, authorized, safe, or allowed. That decision is the relying party's."
}
cryptographically-verified Web Bot Auth signature
A valid signature establishes that the holder of the referenced key signed this request. It does not by itself establish the real-world operator, authorization, trust, or safety.
Worked example — input: a request carrying a valid RFC 9421 Web Bot Auth signature whose Ed25519 key is published at the caller's Signature-Agent directory.
{
"kind": "web-bot-auth",
"tier": "cryptographically-verified",
"statement": "an RFC 9421 HTTP Message Signature validates: the holder of key \"HuaaDCJ5d1JXjy9SLWFoX76L1VWQAAwA1xaowGw8IM8\" signed this request",
"boundComponents": [
"@authority",
"signature-agent;key=\"sig1\""
],
"keyid": "HuaaDCJ5d1JXjy9SLWFoX76L1VWQAAwA1xaowGw8IM8",
"algorithm": "ed25519",
"created": 1791153422,
"expires": 1791153722,
"directory": "https://agent.example/.well-known/http-message-signatures-directory",
"keyMatchedBy": "thumbprint",
"provenance": [
{
"source": "request-header",
"header": "signature-input"
},
{
"source": "request-header",
"header": "signature"
},
{
"source": "key-directory",
"url": "https://agent.example/.well-known/http-message-signatures-directory",
"keyid": "HuaaDCJ5d1JXjy9SLWFoX76L1VWQAAwA1xaowGw8IM8",
"matchedBy": "thumbprint"
}
],
"note": "proves ONLY that the holder of this key signed this exact request, binding the listed components. Per the Web Bot Auth specification this does NOT establish who operates the agent, its organization, or any authorization for the requested action — those remain the relying party's decision."
}
Inspect is experimental (0.x) and stores nothing: it reads a request, returns the evidence, and retains no request, credential, or key data. Source and documentation: github.com/NessGate/nessgate · @nessgate/inspect.