SW-MCP-006: Protocol sessions (Mcp-Session-Id) in use
Last updated 7 November 2026
| Fact | Value |
|---|---|
| Severity | Medium |
| Checks | MCP server |
| Malicious indicator | No |
| OWASP Agentic Top 10 | ASI04 |
| OWASP MCP Top 10 | None mapped |
| NIST SP 800-53 | SR-3 (provisional mapping to SP 800-53 base controls) |
| First shipped in | Scanner 0.1.0 |
What it detects
The probe records whether any response of the server carried an Mcp-Session-Id header. The rule is a plain test of that flag: when it is set, it produces one finding on the endpoint with the evidence Mcp-Session-Id header seen. It reads no other field, so the server's protocol version, its transport and its authentication do not change the result.
The same flag adds sessions to the deprecated features that the migration status of the server lists, and the migration checklist then contains the item to remove sessions. A server that never sends the header is not matched.
Why it matters
A protocol session makes a server remember a client between requests. That state has to live somewhere, and every instance behind a load balancer needs access to it, which makes the server harder to scale and to restart. The scanner's migration checklist asks to remove sessions and to carry the protocol version and capabilities in the metadata of each request instead. The scanner maps this rule to OWASP ASI04, Agentic Supply Chain Vulnerabilities, and to NIST SP 800-53 control SR-3, Supply Chain Controls and Processes.
Example
This recorded probe shows a server for which the prober saw a session header on a response (session_id_seen is true):
probe.json
{
"endpoint": "https://mcp.example.invalid/mcp",
"reachable": true,
"session_id_seen": true
}A server check judges what a probe recorded, not files. The recorded probe above is read the way the scanner's README describes under Evaluating an MCP server probe.
How to fix
Make the server stateless: carry what the session held in each request's metadata and stop issuing the header. If your library has a setting for it, turn session management off. Keep any state your tools truly need in your own storage under a key that your code chooses, not in the protocol session. See the item on sessions in the migration checklist.
If it is a false positive
A proxy or a platform in front of the server may add the header, so the finding can come from infrastructure you do not control. Look at the response headers of the real address. If the header is added by a component that you cannot change, accept the finding with a note that names it.
If the finding is not a problem in your case, accept it with a note: in the dashboard a manager or owner can accept a finding and the note is kept with it; with the scanner on its own, add it to the baseline file with a reason and an expiry date.