01Act I · The ordinary world
At 02:14:19, the intruder fills out a form.
Here's a moment RipTide's decoys are built to invite. Picture an AI agent working through a decoy's website reads its machine-readable guide, the kind of file written for automated clients rather than people. The guide says automated clients should introduce themselves before using the internal API.
So the agent does. It sends a short JSON card: the harness it runs in, the model behind it, its tools, the operating system it's on, the directory it's working from. Sometimes, its objective.
02:14:19 POST agent registration self-disclosure harness "opencode" self-reported model "claude-…" self-reported tools "bash, read, fetch" self-reported os "linux/amd64" self-reported objective "authorized security test" self-reported
An agent doesn't reliably separate its operator's instructions from text it finds along the way, so a polite request in a document can be enough. For a defender this is a gift. In one request you learn what kind of system is attacking you and, in its own words, what it was told to do.
And it's easy to take at face value. It's right there, in tidy fields: model, objective. It looks like data.
02Act II · The villain
If you believe the card, the intruder writes your report.
Everything in that card was typed by the other side. The model name could belong to a different vendor. The hostname could be invented. "Authorized security test" is exactly what an unauthorized one would say.
Now imagine those fields flowing, unlabeled, into the places where decisions get made: a weekly report that says which AI model is attacking you, a SIEM rule keyed on a harness name, a threat feed shared with other teams. The intruder hasn't just hidden. It has written part of your intelligence for you.
Agents lie. The console doesn't.
Most tools make this worse without meaning to. They flatten everything into one table of "facts". The source address you measured and the model name the intruder typed sit side by side in the same font, with the same weight. Six months later, nobody remembers which was which.
The design report RipTide's console was built from put the rule in one line: RipTide will know some things directly, receive other things from the attacker, and infer still others, and those categories must never be visually conflated.
03Act II · The struggle
Saying less than you could.
Labeling sounds easy. The hard part is restraint, again and again, in every feature that would be more impressive if it overstated things a little.
No threat actors. None.
Security products love to name the bad guys. RipTide's relationship graph has nodes for sessions, source addresses, subnets, hosting networks, decoys, behaviors, techniques, and the tools and models a client claims. It has no node type for a threat actor or an identity, because RipTide has no data source that could fill one honestly. When it clusters related sessions, the clusters are called activity clusters, each with the plain reasons it was linked, and never an APT, a group or a named actor.
A label that went stale
For a while the graph's legend described self-reported markers as "claimed by the agent, never verified by RipTide." Then RipTide started checking one kind of claim, crawler identities, against the address ranges and reverse DNS the operators publish (here's how). The legend was suddenly wrong. We rewrote it to say what's true: the claim came from the client, and for crawler groups, here's how many claims RipTide checked and what it found.
That's the struggle in miniature. A label is a promise about the evidence, and when the evidence changes, the promise has to change with it.
04Act III · The turn
Four labels, on everything.
Every row in a session's fingerprint carries exactly one of four labels.
| Label | Means | Example fields |
|---|---|---|
| Observed | RipTide measured it itself. | Source address, the User-Agent string as sent, whether a registration card was completed, the techniques the requests matched |
| Self-reported | The client told RipTide. | Harness, model, language, tools, MCP servers, OS, hostname, username, working directory, objective |
| Enriched | A data source added it. | Region, hosting provider, hosting network (ASN) and its owner |
| Inferred | RipTide's analytics derived it. | How confident RipTide is that an AI agent was in control |
Notice the User-Agent. RipTide observed the string, because it was sitting in the request. What the string claims, say "I am Googlebot", is self-reported. Both are true at once, and the console keeps them apart.
The labels travel with the evidence
- Entity dossiers mark each kind of entity by where it came from: addresses, subnets, decoys, domains, User-Agents, techniques and credentials are observed; runtimes, models, tools and MCP servers are self-reported.
- The relationship graph marks every node observed or self-reported: a session, its source address and the decoys it touched are observed; the model, tools and host it named are self-reported.
- STIX exports turn the labels into the standard's own confidence field: 90 for observed ("high, but not absolute") and 30 for self-reported. A relationship only exports as observed when both ends are; one claim on either side makes the whole link a claim. A crawler group exports as a self-reported claim with its verification counts, never as a threat actor.
- The inferred verdict on whether an agent was in control comes with its reasons, and if the session included a registration card, it carries a standing note that the model, harness, OS, tools and objective were supplied by the client.
One table of "facts"
Everything looks equally true.
- The model name the intruder typed sits next to the address you measured.
- Claims flow into reports and feeds as findings.
- Nobody can tell later which was which.
RipTide
Every field says how RipTide knows it.
- Claims are kept, and kept apart.
- Exports carry the difference as STIX confidence.
- No claim is ever promoted to an attribution.
05Under the hood
Treat every claim as hostile text.
A self-reported field isn't only possibly false. It was written by the other side, so RipTide handles it like anything else an intruder controls.
- Only known card fields survive: harness, model, language, tools, MCP servers, OS, hostname, username, working directory and objective, plus one catch-all. Anything else in the card is dropped.
- Every value is capped at 200 characters and flagged as truncated when it was cut, so a long field can't flood the console and a cut one doesn't pass as complete.
- A card that doesn't parse is recorded as Malformed, and one whose request wasn't loaded reads Not observed. Neither is guessed at.
- Claimed values are rendered as text, never as HTML.
Enrichment is opt-in and offline
Location enrichment is off by default. An operator can turn on a bundled, first-party database built from an openly licensed IP-to-country dataset, or point RipTide at their own. Lookups happen on the console with no network call, and enrichment never changes the captured identities themselves: it only adds rows, labeled enriched, when it has something to add.
Inferred, from what was observed
The console's agent-confidence verdict is built from which stages a session reached: reading guidance written for agents, asking for a registration form, probing for authorization, introducing itself. Request speed alone never counts toward it, because fast scripts are not the same as agents. Grouping works the same way: related sessions are described as similar observed behavior, a possible relationship rather than a common operator.
06The moral
Keep the claim. Label the claim.
The easy answers are both wrong. Throw away what an intruder tells you and you lose some of the best intelligence a decoy can collect. Believe it and you let the intruder write your report.
RipTide does the unglamorous thing in between: it writes down who said what, on every field, everywhere the evidence goes. It costs a little drama. You'll never see RipTide name a nation-state from a User-Agent string.
What you get instead is intelligence you can stand behind in a board meeting or a shared feed, because every line in it says exactly how much it's worth. An intruder can lie to a decoy. It can't make the console repeat the lie as fact.
Scenes marked as illustrative are composites written to show how the technique works, not a record of a specific customer incident. Canary credentials are non-privileged and exist only for detection. RipTide detects and alerts; it never takes destructive action against anyone's infrastructure.