microsoft / microsoft/agent-governance-toolkit
AgentMesh relay: connect-frame DID proof-of-possession is replayable within its 5-minute window
- Dominant language
- Python
- Stars
- 6.3k
- Forks
- 1.1k
- Avg merge
- 5d 11h
- Merged PRs (30d)
- 142
Description
### Summary
`_verify_connect_pop` in `agent-governance-python/agent-mesh/src/agentmesh/relay/app.py` signs
only an ISO-8601 timestamp and accepts it inside a ±5 minute window
(`DID_POP_REPLAY_WINDOW`). The signature is not bound to a server-issued nonce, to the relay
URL, or to the TLS channel, so a captured `connect` frame can be replayed within that window
to authenticate as the captured DID.
### Why it matters
A replayed connect frame *owns* the mailbox, so it passes every downstream identity check:
- it satisfies the recipient-ownership check on `ack`, so it can acknowledge and therefore
delete the victim's queued messages;
- it satisfies the frame `from`-binding, so it can emit frames as the victim;
- it displaces the victim's live socket.
Note this is not a weakness in those controls — they are working as designed against a
connection the relay considers authenticated. The gap is upstream, in what "authenticated"
means at connect time.
### Suggested fix
Either of:
1. **Challenge-response nonce.** Relay sends a random nonce on connect; the client signs it.
2. **Bind the proof to the channel.** Sign `relay_url || nonce` (or a TLS exporter value)
instead of a bare timestamp.
Both change the connect handshake on the client and the relay, so this needs its own change
with a compatibility story for existing clients.
### Current mitigations
- TLS is required in production, which prevents passive capture of connect frames on the wire.
- As of #3411 a displaced socket is closed with `WS_CLOSE_SESSION_REPLACED` (4006) instead of
`1000`, and the client raises it through `onError`, so the displacement is now observable
rather than silent. That is detection only — it does not prevent the takeover.
### Provenance
Raised by @MohammadHaroonAbuomar in review of #3411, who confirmed it with a probe
(mailbox takeover + queued-mail deletion) and asked for it to be filed separately as
pre-existing. Recorded under "Known gaps" in
`docs/security/audits/2026-07-21-agentmesh-message-authentication-hardening.md`.
Contributor guide
Research direction
Start at _verify_connect_pop in agent-governance-python/agent-mesh/src/agentmesh/relay/app.py and inspect how DID_POP_REPLAY_WINDOW is applied during the connect handshake. Review the corresponding client and relay handshake paths, then define completion as a proof bound to a nonce or channel context with existing-client compatibility addressed.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- authentication, backend, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100