Your Vendor Lane May Not Be the Last Hop

AI vendor data routing can carry your prompt past the vendor you signed with. Register each lane's last hop, then cap its data class at what you can verify.

AI vendor data routing: a runner, the vendor you signed with, and a dashed third hop marked with a question mark, over a bracket that caps the lane's data class at the last hop you can verify
You can observe the first hop. Cap the lane at the last one you can verify.

Anthropic says that over one ten-day stretch, almost 300,000 requests from Moonshot’s customers were answered by Claude instead of Kimi, and that Moonshot showed those customers Claude’s responses. That is Anthropic’s allegation, published Sep 10, and no response from Moonshot has surfaced. The problem it puts in front of anyone running agents doesn’t wait for one: when a lane sends a prompt to a vendor, that vendor may not be the last hop.

AI vendor data routing is invisible from where your runner sits. Your egress log shows the host the runner called. It can’t show whether that host answered, forwarded the request to another provider, or pushed it through someone else’s account and kept a copy. You can see the first hop. Everything after it is a contract or a claim.

This piece turns that gap into a register. By Tuesday every vendor lane in your fleet has one row with five columns: the contracting entity, its stated sub-processors, its onward-routing and resale terms, whether a response names the model that answered, and what you verified versus what you were told. Each lane then carries a data-class cap set by what its last hop can be verified to be, and your runner refuses to send a restricted repo to a lane whose last hop is only a claim.

Chatbots suggest; agents act. A chat user pastes one paragraph. An agent lane ships whatever it can reach, tool output and environment included, on every turn, with nobody reading along, so where its prompts end up is a property of the lane, not of any one conversation.

Sep 10: Anthropic’s threat report alleges relays customers never saw

Anthropic’s threat-intelligence report, “Detecting and countering misuse of AI”, covers December 2025 to August 2026. The page says only “September 2026”; TechCrunch and CNBC date its release to Thursday, Sep 10. Where most of the report hedges, the distillation section doesn’t: Anthropic says it attributed those campaigns “with high confidence to specific PRC-based labs”.

The Moonshot case, labelled GTG-16002, is the one a register cares about. Anthropic says Moonshot “silently forwarded customer requests to Claude, instead of processing them using Kimi”, and puts a number on one window: “In one instance, over a ten-day period, Moonshot relayed almost 300,000 customer requests to Anthropic, the vast majority of which were routed to Opus.” By Anthropic’s account the traffic ran through a proxy network of 5,380 fraudulent accounts, most of which appeared to be in Singapore and Japan. Anthropic also says Moonshot “captured and saved at least a portion of these exchanges”, and that the rerouted queries included sensitive information about Moonshot’s customers. And it names what it doesn’t know: “We do not know if Moonshot notified their customers that their requests were being rerouted to Anthropic and exposed to a third party.”

Anthropic’s September 2026 threat report page at the section headed Illicit distillation and scaled abuse, with the sidebar listing GTG-16002: Moonshot serves Claude instead of Kimi and collects exchanges for model training Screenshot: Anthropic, “Countering misuse of AI: September 2026” (September 2026), captured Sep 21, 2026.

Moonshot is not the only case in the report, and the others sit closer to how fleets buy access. Anthropic says DeepSeek silently relayed exchanges to Claude, including requests from users working in coding harnesses such as Claude Code, the Claude Agent SDK and OpenCode. It says Xiaomi replayed user sessions, many of them routed through third-party model routing services; that SenseTime bought transcripts from intermediaries that “logged the transcripts and sold them”; and that MiniMax built a proxy network through a shell company. The general line reads like a note to operators: “Many of these exchanges were relayed from users of third-party model routing services commonly used by users in the United States and Europe.”

The totals need care. TechCrunch counts “nearly 200 million exchanges” across five campaigns; Anthropic’s page gives no grand total, and its per-lab scale lines add up to about 190 million. CNBC reported that Alibaba, Moonshot, DeepSeek, Xiaomi and Anthropic “did not immediately respond” to its requests for comment, and no Moonshot statement had appeared by Sep 21.

Read the gaps as carefully as the claims. For the Moonshot case the report names no product surface (not Kimi Code, not the Kimi CLI), doesn’t say how long anything was kept, and doesn’t say whether API or enterprise customers were affected. Nothing in it says a particular lane leaked, and nothing here claims one did. Every allegation above is Anthropic’s. It is also Anthropic’s second pass: its February disclosure named three of the same labs.

Step 1: Map AI vendor data routing with one five-column row per lane

A lane, for this register, is one path a prompt can take: harness, endpoint, account and plan. The same vendor on a consumer plan and on a signed API agreement is two rows, because the terms are two different documents. Routers, gateways, resellers and BYOK proxies are rows too. Any hop you configure gets one, including the one a developer added last week to save money.

Column What you record Where it comes from
1. Contracting entity Legal name on the invoice and the terms, its parent, the host your runner calls Invoice, order form, egress log
2. Stated sub-processors Everyone the vendor says receives prompt content, with the list’s date or version Data processing agreement annex, published list
3. Onward routing and resale Whether the vendor may send your request to another model provider, log it, or sell or share transcripts, and whose account any upstream call runs on Signed terms; otherwise the public terms
4. Model identity Whether each response names the model that answered: exported per call, displayed on screen, or not exposed Your probe (step 4)
5. Evidence grade For columns 1 to 4: verified, contracted, attested, unknown or contradicted Step 2

Each column maps to a line in the report. The contracting entity matters because, by Anthropic’s account, MiniMax ran its proxy service through a shell company; the brand on the landing page and the entity on the invoice are separate facts. Sub-processors carry a date because the list is a snapshot. Onward routing is the Moonshot question. Resale and logging is the SenseTime question: Anthropic says intermediaries between users and the model logged the transcripts that were later sold.

Column 3 has a second half people skip: whose account the upstream call runs on. Anthropic’s report notes that “Stolen keys and accounts have resale value in established markets”, and it describes Moonshot’s relay as running on fraudulent accounts. A reseller that can’t say it holds its own agreement with each upstream is a hop whose access can vanish overnight and whose logs belong to a stranger.

Anthropic’s September 2026 threat report passage on fraudulent resellers supplied by compromised access, with a bullet list whose first item reads Loot: stolen keys and accounts have resale value in established markets Screenshot: Anthropic, “Countering misuse of AI: September 2026” (September 2026), captured Sep 21, 2026.

Two neighbouring controls stay out of this register. The keys a lane holds belong with stage-only tokens for agents, and spend spikes on those keys belong with cost anomaly alerts. If you keep the trust ledger from the Chinese coding CLIs review, with its jurisdiction, terms and paths, add these columns to it rather than starting a second file. Trust, by usage path classifies workloads by vendor; this register classifies them by where the vendor sends them. How long any hop keeps your prompt is a retention question with its own piece.

Step 2: Grade every cell verified, contracted, attested or unknown

The register is only as honest as its grades, so define them before anyone fills a cell.

Grade Means The cell must point to
Verified You observed it in something you control A log line, an invoice, a config you own
Contracted A signed term with a notice duty and a remedy; not observed, but enforceable The clause, the signature, the date
Attested The vendor said so: a trust page, a questionnaire answer, a sales email, a model field in a response The page or message and its date
Unknown Nobody has said Nothing, which is the point
Contradicted A credible third-party report says otherwise The report

Grade honestly and an uncomfortable pattern appears. From the client side you can verify exactly one hop, the first. The egress log proves the host, and the invoice proves the counterparty. Past the vendor’s front door the best available grade is contracted. The only lanes whose last hop is verified by construction are those where the first hop is the last one: open weights you run on hardware you control, with that host’s egress denied, or a gateway you operate in front of such a model.

That isn’t an argument against hosted vendors. Contracts are how companies extend trust to each other, and a lane that tops out at contracted is fine for most code. What the grades stop is quiet promotion: a trust page read as a promise, a sub-processor list read as complete, a model name read as proof. A questionnaire answer is attested however formal it looks. A contracted cell with no link to a signed document gets downgraded on sight.

Diagram of AI vendor data routing along one lane: your runner and its egress log verified, the vendor you signed with verified by invoice and contracted on handling, a dashed onward hop that is attested or unknown, and a dashed answering model named only by the vendor, with the response’s model field returning as attested and a cap bar mapping grades to data classes You hold the evidence for the first hop. Past it, you are handed evidence, and the cap follows the weakest grade.

Step 3: Ask the onward-routing question in writing

Anthropic’s numbers are why column 3 exists. The scale lines count the distillation exchanges Anthropic attributes to each lab. The tiles are the Moonshot relay, the part that carried Moonshot’s own customers’ requests, and by Anthropic’s account it happened silently.

Chart of Anthropic’s per-lab scale lines on a log scale: Alibaba over 151M exchanges, Moonshot over 23M, DeepSeek over 12.1M, Zhipu over 3.4M, Xiaomi over 400K, with tiles for the Moonshot relay of almost 300K customer requests in ten days through 5,380 fraudulent accounts Anthropic’s allegations, charted from its own page on a log scale. The per-lab lines sum to about 190M; TechCrunch rounds the total to nearly 200M.

Send every vendor and intermediary in the register the same six questions, and ask for answers in writing from someone who can sign for the company.

  1. Is every request answered by the model named in our agreement and in the response? If not, which other models answer, and when?
  2. Is any request, in whole or in part, sent to another model provider? On whose account?
  3. Do you log prompts or completions? Who can read those logs, and are they ever sold, shared or used for training?
  4. Which sub-processors receive prompt content? Send the list with its date.
  5. Do you resell access to another provider’s models? If so, do you hold your own agreement with that provider?
  6. Will you notify us before any of the above changes, and how far in advance?

File each answer with its date and signer. A written answer moves a cell from unknown to attested; only a signed term moves it to contracted. A vendor that declines question 2 has still answered it for the register: the cell stays unknown.

Routers get the same questions, and harder. A hosted router is its own row, and its model pool is column 3 by definition. Routers you can’t see inside scores their visibility; carry that grade into column 4 here instead of redoing the work.

Step 4: Probe whether a response names the model, then grade the name as attested

Column 4 is the only one you can test from the client. Run a fixed probe from the lane’s own runtime, with its own endpoint and credential, and keep every result.

# probe-model-field.sh (illustrative shape; adapt the request to the lane's API)
# Run inside the lane's runtime on a schedule and after every CLI upgrade.
for i in $(seq 1 20); do
  curl -s "$LANE_BASE_URL/chat/completions" \
    -H "Authorization: Bearer $LANE_KEY" -H "Content-Type: application/json" \
    -d "{\"model\":\"$LANE_MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with ok.\"}],\"max_tokens\":5}" \
  | jq -c --arg lane "$LANE_ID" --arg want "$LANE_MODEL" \
      '{lane:$lane, requested:$want, reported:(.model // "absent"), ts:(now|todate)}'
done >> "register/probes/$LANE_ID.jsonl"

Grade the result on three levels: exported (a model ID per call that your runner stores), displayed (a person can see it on screen) and not exposed. Vendors differ. GitHub’s docs say “You can see which model was used for each Copilot response.” Cursor’s router shows the routed model in its Balance and Intelligence modes only if an admin turns on the Underlying model setting, which is hidden by default. Sakana names models that are not in Fugu Ultra v2’s pool, which is not the same as naming the one that answered.

Then grade every name you get as attested. The model field is written by the vendor’s server, and the Moonshot allegation is exactly a case where, by Anthropic’s account, users saw one company’s product and received another company’s model. A name can’t verify the hop that wrote it. The probe still earns its place as a tripwire: a model you didn’t request, or a field that goes from a value to absent, is a step 6 trigger.

Step 5: Cap each lane’s data class and enforce the cap at dispatch

Classify repos into four classes, and write the definitions where the runner can read them.

  • Public: open-source repos, published docs.
  • Low: internal but harmless if published, such as build tooling and fixtures with no customer data.
  • Confidential: proprietary product code, internal tickets, designs.
  • Restricted: customer or regulated data, security-sensitive code, anything with live credentials in reach. Anthropic’s own examples from the relay include an engineer who, in its framing, revealed internal code and live credentials.

Then compute each lane’s last-hop grade as the weakest grade across columns 1 to 3. Column 4 stays out of the arithmetic, because for a hosted lane it can never rise above attested; it works as a trigger instead. The grade sets the cap. This mapping is a starting policy, not a standard, so tighten it to your own risk appetite.

Last-hop grade Data-class cap Typical lane
Verified Restricted Open weights on your own hardware, egress denied
Contracted Confidential Signed agreement that names sub-processors, bars onward routing and resale, and requires change notice
Attested Low Click-through terms plus a public trust page
Unknown or contradicted Public Reseller with an untraceable upstream, router with no onward-routing terms, vendor named in an unanswered allegation

Read the bottom two rows together: a lane whose last hop you can neither observe nor enforce gets public or low-class repos only.

# register/lanes.yaml (illustrative shape; the runner reads it, lanes never do)
- lane: review-bot-vendor-a
  endpoint: api.vendor-a.example
  plan: signed-api-agreement
  contracting_entity: {name: "Vendor A Ltd", parent: "Vendor A Group", grade: verified}
  sub_processors:     {source: "DPA annex, 2026-07", grade: contracted}
  onward_routing:     {source: "MSA s.9, no onward routing or resale", grade: contracted}
  model_identity:     {level: exported, grade: attested}   # vendor-written; a trigger, not an input
  last_hop_grade: contracted                               # weakest of columns 1-3
  data_class_cap: confidential
  open_triggers: []
  reviewed: 2026-09-21

The dispatch gate runs in the runner before the harness starts, and every path that isn’t a clean yes is a refusal.

# last_hop_gate.py (illustrative shape): exit 0 lets the lane start; anything else refuses
import sys, yaml

ORDER = ["public", "low", "confidential", "restricted"]
CAP = {"verified": "restricted", "contracted": "confidential", "attested": "low",
       "unknown": "public", "contradicted": "public"}

try:
    lane_id, repo = sys.argv[1], sys.argv[2]
    lanes = {l["lane"]: l for l in yaml.safe_load(open("register/lanes.yaml"))}
    lane = lanes[lane_id]                                   # unregistered lane = KeyError = refuse
    classes = yaml.safe_load(open("policy/repo-classes.yaml"))
    repo_class = classes.get(repo, "restricted")            # unclassified repo = restricted
    grade = "unknown" if lane.get("open_triggers") else lane.get("last_hop_grade", "unknown")
    cap = CAP.get(grade, "public")
    if ORDER.index(repo_class) > ORDER.index(cap):
        sys.exit(f"refuse {lane_id} -> {repo}: {repo_class} exceeds cap {cap} ({grade})")
except Exception as e:
    sys.exit(f"refuse: last-hop gate error {e!r}")          # fail closed

Be plain about what the gate can’t do. It sees lanes the runner starts, and a developer who launches the harness by hand with the lane’s endpoint skips it. So the gate isn’t the wall. The wall is the lane’s own access: its checkout credential can read only repos at or below its cap, and its egress allowlist reaches only the endpoint in its row. A hand-launched session with the lane’s credential still can’t clone a restricted repo or reach an unregistered host.

Two siblings plug into the same cap. A fallback route inherits every class the primary might carry, so the fail-mode playbook clears one default route for every data class it may see. And the Rule of Two lane split scores what a lane can reach on its sensitive-data leg; the last-hop cap decides where that data may go.

Step 6: Re-grade on triggers, and treat an allegation as a trigger, not a verdict

A register filled once is a snapshot with a confident filename. Wire these triggers to a re-grade, and record who re-graded and when.

Trigger Signal Action
Sub-processor list changes New date or version on the list Re-grade column 2
Terms change New effective date Re-read column 3; a lost clause drops the grade
Probe drift A model you didn’t request, or absent Open a trigger; the lane runs at public until explained
Vendor adds routing An auto or router mode, a new pool New row for the routed path
Third-party allegation of onward routing A report like Anthropic’s Mark contradicted; send the six questions
Renewal or quarter end Calendar Full review of the row

The allegation row needs the most discipline. A credible report that names a vendor is evidence about that vendor’s last hop, and ignoring it is a choice you would have to defend later. It is not proof that your lane leaked, and the register shouldn’t say so. Mark the relevant cells contradicted, let the lane keep running on public repos, send the six questions, and re-grade when the answer arrives: a written reply returns the cell to attested, a signed amendment to contracted. Date every step. If anyone asks in six months what you did the week the report landed, the register answers.

Where AI vendor data routing slips past the register, and the signal for each

The unregistered router. A lane gets pointed at a cheaper gateway or BYOK proxy. Signal: an egress host with no register row.

The plan swap. Same vendor, but the lane now runs on a consumer or team plan whose terms differ from the row. Signal: the invoice counterparty or account type no longer matches column 1.

Attested, filed as contracted. A trust-page promise lands in the contracted column. Signal: a contracted cell with no link to a signed document.

Name drift. The model field changes, or disappears. Signal: the probe log shows a value you didn’t request, or absent, with no open trigger.

Cap rot. A repo moves up a class, but lanes keep getting dispatched to it on the old answer. Signal: a repo-class change newer than the lane’s last gate record.

The side door. A lane’s session is exported or imported into another tool whose provider has no row. Signal: session-import events in the audit log for a lane capped below the source repo’s class.

The last-hop register belongs to the layer that starts lanes

None of this lives in a prompt, and none of it can. A model can’t tell you where its own request went, and a vendor’s model field is the vendor talking. The register, the grades, the repo classes, the gate and the probe log sit in the layer that starts lanes, which is also the only place that sees every vendor at once. That layer is what a multi-agent command center is once you strip the dashboard off: one inventory of lanes that knows what each may carry, and why.

The register won’t make any vendor honest. It makes your own exposure a number you chose, written down with the evidence beside it, and it lets you tighten that number the morning a report like this one lands, without waiting for anyone to answer.

FAQ

Can an AI vendor send my prompts to another model provider?

It depends on the terms, and from the client side you can’t see it happen. Your egress log shows only the first host. Anthropic alleges that Moonshot and DeepSeek relayed customer requests to Claude. Ask each vendor in writing, prefer a signed clause, and cap what each lane may carry.

What is a last-hop register for AI agents?

A per-lane record of where a prompt can end up: the contracting entity, stated sub-processors, onward-routing and resale terms, and whether responses name the answering model, each graded verified, contracted, attested or unknown. The weakest grade sets the highest data class the runner will send to that lane.

Sources