Security brief: an MCP server that read a refusal as approval, a drive-by hole in a local vault server, secrets that follow a hostile MCP server, and A2A chats shared across tenants
The advisory databases published another batch for agent infrastructure: obsidian-tc treated a refused human confirmation as approval and exposed its HTTP transport to any web page, FastMCP clients could hand OAuth secrets to a hostile server, and the Strands Agents SDK and LangGraph stores leaked data across tenants. No new exploitation was confirmed, so the level steps down from yesterday's LiteLLM incident.
Covers Fri 23 Oct 08:00 to Sat 24 Oct 08:00 CEST
Quiet window for incidents: I found no new confirmed exploitation of agentic software and no agentic CISA KEV entry, but the CISA catalog itself could not be opened (only search extracts of its bulletins). Only github.com and a few vendor hosts resolved here, so GitHub advisories, release pages and pull requests were read in full while the eMudhra incident and the 'protocol pivoting' disclosures rest on search extracts and are tagged accordingly. About 28 searches and 30 page fetches. Several advisories carry earlier GitHub dates (obsidian-tc 3 Jul and 26 Sep, FastMCP 20 Oct) and reached the reviewed database or NVD inside the window; I cover them now because PADAWAN had not. The LiteLLM incident is not repeated; its threat alert from yesterday still stands, and the vendor's status page could not be opened to check for updates.
Act now
- Upgrade obsidian-tc to 1.31.4 or later, and stop exposing its HTTP transport with auth mode 'none' Versions below 1.3.1 accept any request on 127.0.0.1/mcp from a web page the user visits (no Origin or DNS-rebinding check); versions 1.13.0 to 1.31.3 run destructive tools after a human declined. Check with `npm ls obsidian-tc`. If you cannot upgrade, use stdio or require JWT auth.
- Set `issuer` on FastMCP OAuth client providers and rotate secrets that went to untrusted servers Applies to FastMCP 4.0.0a1 to 4.1.1 using ClientCredentialsOAuthProvider or PrivateKeyJWTOAuthProvider against user-supplied MCP server URLs. Upgrade to 4.1.2 or later (4.1.3 is current), set `issuer` to your authorization server, and rotate any client secret that may have reached an unvetted endpoint.
In brief
- obsidian-tc, an MCP server for Obsidian vaults, accepted a valid 'request state' as proof that a human approved a destructive action even when the human declined (CVE-2026-115477, fixed in 1.31.4). Its separate CVE-2026-77363 (CVSS 9.6) let any web page the user visits read and write the vault over loopback (fixed in 1.3.1).
- FastMCP 4.0.0a1 to 4.1.1: OAuth client-credentials providers did not bind to an issuer, so a malicious or compromised MCP server could redirect the client secret to its own authorization server. Upgrading is not enough; set `issuer` and rotate secrets sent to untrusted URLs. A second advisory: component authorization was skipped for transformed components on direct calls.
- Strands Agents SDK's A2A server shares conversation history across callers with different context IDs (CVE-2026-115419, 8.6; fixed in Python 1.43.0 and TypeScript 1.5.0), and LangGraph's Postgres and SQLite stores let a dotted namespace label reach another tenant's data (CVE-2026-115883, fixed in 3.1.3 and 3.1.2).
- Three unpatched or lightly patched pieces worth a look: AgenticSeek's server ships Flask debug mode on all interfaces (CVE-2026-115727, 9.2), the Elixir req_llm library disabled certificate checks on OpenAI WebSocket paths (CVE-2026-107685, 9.1, fixed in 1.29.0), and Goose's terminal integration sends shell history unredacted to the model provider (CVE-2026-111079, 7.4, no fixed version listed).
- Two items filed with lower confidence: the 'protocol pivoting' SSRF class reported across five MCP servers, and eMudhra's compromised intermediate CAs, which reached agent stacks through bundled trust stores (FastMCP 4.1.3 and 3.4.11 now require an updated certifi).
Executive summary
Nothing in this window is a live campaign, which is why the level drops from yesterday’s high to elevated. What the advisory databases show instead is the same engineering gap from several directions: the checks that protect an agent integration are applied at one layer and trusted at the next. A human’s “no” is converted into a token that the server accepts as a “yes”. A local server trusts any caller on loopback, including a web page. A client trusts whichever authorization server a remote tool names. A shared agent server trusts a caller-chosen conversation ID.
None of these needs a new defence. Each needs a boundary moved to where the decision is actually made. The LiteLLM alert from yesterday remains the one item that needs response work today if you ran 1.107.0.
Recommendation (opinion): spend today on two inventory questions. Which MCP servers can delete or rewrite data, and does their confirmation step verify an answer from a human or merely a token from the client? And which of your agent servers serve more than one user, and what keys their conversation and memory state?
Act now
- obsidian-tc: upgrade to 1.31.4 or later; do not run its HTTP transport unauthenticated.
- FastMCP client credentials: set
issuer, upgrade to 4.1.2 or later, rotate secrets that may have gone to untrusted servers.
Vulnerabilities
| Product | Flaw | Severity | Fixed in | Notes |
|---|---|---|---|---|
| obsidian-tc before 1.3.1 | Streamable HTTP transport has no Origin or DNS-rebinding check; with default auth.mode: "none" a web page drives the vault as caller http-local with all scopes (CVE-2026-77363) | Critical, 9.6 | 1.3.1 | NVD 12 Oct; reviewed on GitHub 23 Oct |
| obsidian-tc 1.13.0 to 1.31.3 | A call-bound requestState is accepted as approval even when the human declined or cancelled (CVE-2026-115477) | High, CVSS 4.0 7.1 | 1.31.4 | Needs a client that echoes state after a decline; residual client-side risk stays |
| obsidian-tc 1.0.1 to 1.31.3 | Memory tools overwrite notes they do not own and can leave the database and notes inconsistent (CVE-2026-115478) | High, 7.1 | 1.31.4 | Requires the write:memory scope |
| FastMCP 4.0.0a1 to 4.1.1 | M2M OAuth providers accept no issuer; a hostile server’s advertised authorization server receives the client secret (GHSA-vqqp-x5qm-5qp4, no CVE) | Moderate, CVSS 3.1 5.9 | 4.1.2, plus set issuer | Rotate secrets sent to untrusted URLs |
| FastMCP 3.0.0 to 3.4.9, 4.0.0 to 4.1.1 | Authorization checks the original component; a transform that changes its metadata lets a direct call reach a tool, resource or prompt the policy denies (GHSA-7xgj-8392-5q4r, no CVE) | Moderate, 6.8 | 3.4.10 and 4.1.2 | Overlapping proxy templates are the exposed pattern |
| Strands Agents SDK (Python before 1.43.0, TypeScript before 1.5.0) | A2A server shares conversation history across callers with different context_id (CVE-2026-115419) | High, CVSS 4.0 8.6 | 1.43.0 and 1.5.0 | Needs an authenticated caller on a multi-tenant server |
| langgraph-checkpoint-postgres before 3.1.3, -sqlite before 3.1.2 | Namespaces joined with dots: ("tenant","bob") equals ("tenant.bob",); get, search, delete and batch accepted dotted labels (CVE-2026-115883) | Moderate, CVSS 4.0 6.0 | 3.1.3 and 3.1.2 | LangSmith Cloud already patched; self-hosted must upgrade |
| AgenticSeek before commit 409840c | llm_server/app.py runs Flask debug mode bound to all interfaces; attacker who derives the Werkzeug debugger PIN runs code (CVE-2026-115727) | Critical, CVSS 4.0 9.2 | Commit 409840c | Unreviewed advisory; no release version listed |
| req_llm 1.9.0 to before 1.29.0 (Elixir) | WebSocket client starts with certificate verification off (WebSockex default); on-path attacker reads and alters OpenAI Responses, Realtime and Codex sessions, including the bearer token (CVE-2026-107685) | Critical, CVSS 4.0 9.1 | 1.29.0 (implied by range) | HTTP streaming paths verify certificates |
| Goose, terminal integration enabled | Shell history, including typed secrets, is sent unredacted to the configured model endpoint (CVE-2026-111079) | High, CVSS 3.1 7.4 | Unknown | Unreviewed; affected versions not stated |
| MLflow 3.12.0rc0 to before 3.17.0 | Unauthenticated scorer endpoint instantiates an attacker-named class; with TruLens packages installed it becomes SSRF through the LiteLLM provider (CVE-2026-115886) | Moderate, 6.5 | 3.17.0 | Precondition: optional TruLens packages |
obsidian-tc: a refusal that still approves
What happened. obsidian-tc is an MCP server that gives an agent read and write access to an Obsidian vault. Its advisories describe three separate defects across two trust boundaries. The first, CVE-2026-77363, is that the Streamable HTTP transport had no Origin validation or DNS-rebinding protection, so with the default loopback setting and auth.mode: "none" a request from a malicious web page to http://127.0.0.1/mcp was accepted as caller http-local with scopes ["*"] (fixed in 1.3.1). The second, CVE-2026-115477, is that on a deployment with a JWT secret set, a client speaking the 2026-07-28 protocol revision could run destructive tools after the human refused, because the server accepted a valid call-bound requestState as approval whatever the human answered (fixed in 1.31.4). The third, CVE-2026-115478, is that five memory tools overwrote a vault note they did not own.
Analysis. The approval flaw is the more instructive one. On the modern wire the server asks the client to elicit a confirmation and hands back a state blob; when the client resubmits, the server checks that the state belongs to the same call. That proves the resubmission is the same request, not that a person said yes. The advisory is candid about the residual risk: a malicious or non-compliant client can still answer its own elicitation with an approval, because the server cannot verify that a human saw the form. That is inherent to a client-driven confirmation step, and it matches the lesson of 22 Oct, where headless agents had an approval gate that returned true when nobody was watching. The DNS-rebinding flaw is the familiar local-server pattern: an MCP server bound to loopback is reachable by any page in the user’s browser unless it checks the Host and Origin headers, and the vault’s contents (notes, often with credentials) become readable and writable through the browser. Preconditions differ: the rebinding path needs the user to visit a page while the server runs; the approval path needs a client that echoes state after a decline (a buggy client, or an attacker-controlled one); the overwrite path needs a caller with the write:memory scope. Blast radius is the vault. OWASP mapping: LLM06 Excessive Agency, and Agentic Top 10 tool misuse; MITRE ATLAS exfiltration and impact via an exposed tool. Compare the local-server cases in the 20 Oct brief and the Storybook dev server on 22 Oct: a browser tab is a way into a developer machine.
Why it matters. Elicitation, the MCP mechanism for asking a user a question mid-call, is becoming the standard way to gate destructive tools. If servers treat the client’s echo as the answer, the gate protects against honest mistakes and not against a compromised or hostile client. The same shape is in the open asynchronous approval proposal (SEP-2848).
Mitigation and detection. Upgrade to 1.31.4 or later. Until then use the stdio transport or leave the JWT secret unset so the state path is never offered; for the rebinding flaw, require JWT authentication or bind behind a proxy that validates Origin. Check logs for destructive tool calls that follow a declined or cancelled elicitation, and for HTTP requests to the MCP port carrying a browser Origin header. For your own servers: validate Host and Origin on every local HTTP listener, and make the approval a signed, single-use artefact the server itself creates for a specific human response.
Recommendation (opinion): upgrade now if you run obsidian-tc, and treat any “confirm” step you build on MCP as advisory until the server verifies the answer, not the token. For destructive tools, add a server-side policy (soft delete, snapshots) that does not depend on the client behaving.
Sources: GHSA-pqh8-4pj7-32xx · GHSA-737x-cwfr-5vvc · GHSA-r3g7-r4hr-m258
FastMCP: secrets that follow the server’s advertisement
What happened. Two FastMCP advisories (no CVE assigned) were updated on 23 Oct. In 4.0.0a1 to 4.1.1, ClientCredentialsOAuthProvider and PrivateKeyJWTOAuthProvider did not accept or enforce an issuer, so a malicious or compromised MCP server could advertise a different authorization server and receive the client secret or a signed assertion. The fix in 4.1.2 adds an issuer parameter and isolates cached tokens by issuer, but the advisory says upgrading alone is not enough: the caller must set issuer, and omitting it only raises a deprecation warning. The second advisory concerns server-side authorization: a transform could change the metadata the policy uses, and a direct lookup checked the original component but returned the transformed one, so a client that knew an identifier could call a tool or read a resource the policy denied (3.4.10 and 4.1.2).
Analysis. The first is a confused-deputy flaw in the client: the party that decides where credentials go is the party being connected to. It sits next to a hardening the MCP Python SDK already shipped on 7 Sep, which validates the authorization server’s issuer (see the 22 Oct signal), and it shows why that check belongs in every client library, not only the reference one. Preconditions: a machine-to-machine client pointed at a server URL the operator does not control, such as a user-supplied connector. Blast radius is whatever the leaked secret is allowed to do. The second flaw is the pattern of authorizing before a transform and serving after it. OWASP: Agentic Top 10 identity and privilege abuse; ATLAS: credential access.
Mitigation and detection. Upgrade to 4.1.2 or later (4.1.3 is current), set issuer to your authorization server, and rotate client secrets used with any URL you did not vet. Review logs for token requests to authorization servers other than yours. For the authorization bypass, enforce policy at the handler boundary and avoid overlapping proxy templates for protected resources.
Recommendation (opinion): never let a remote MCP server choose where your client authenticates. Pin the authorization server in client configuration, and refuse metadata that points elsewhere.
Sources: GHSA-vqqp-x5qm-5qp4 · GHSA-7xgj-8392-5q4r · FastMCP releases
Tenant isolation in agent state: Strands A2A and LangGraph stores
What happened. The Strands Agents SDK advisory says its A2A server, under certain conditions, shares conversation history across callers with different context_id values; in a multi-tenant deployment an authenticated remote user could read another caller’s history or influence the model’s behaviour for others (CVE-2026-115419, fixed with an agent factory that isolates state per context in Python 1.43.0 and TypeScript 1.5.0). There is no workaround short of one server instance per tenant. Separately, the LangGraph Postgres and SQLite stores join namespace labels with a dot, so ("tenant","bob") and ("tenant.bob",) become the same text; put rejected dotted labels, but get, search, delete, list_namespaces and batch operations did not, allowing reads, deletes and overwrites in another namespace (CVE-2026-115883, 3.1.3 and 3.1.2).
Analysis. Both are failures of the key that separates one tenant’s state from another’s. In Strands the key is a protocol field the caller supplies; in LangGraph it is an ambiguous string encoding. They continue the vLLM cache-key cases from 23 Oct: a client-chosen or ambiguous identifier trusted as an isolation boundary. Preconditions: authentication exists but is not tied to the state key, and the attacker holds a low-privilege account. Blast radius is conversation history, which in agents often contains tool outputs, secrets and customer data, plus the ability to steer another user’s session. The Strands case is also a data point for A2A: the protocol’s context ID is a routing hint, not an authorization decision. OWASP LLM02 Sensitive Information Disclosure; Agentic Top 10 memory and context poisoning.
Mitigation and detection. Upgrade; until then serve one A2A instance per tenant and never accept state keys from a caller without binding them to the authenticated principal. In LangGraph stores, derive the namespace from the principal server-side, and call validate_op_namespace for custom stores. Test with two accounts: can account B read, search or delete account A’s thread or memory by choosing its ID?
Recommendation (opinion): treat any shared agent server as a multi-tenant database and test it like one. The two-account check takes an hour and finds this class reliably.
Sources: GHSA-4v6f-7vjh-6x4m · GHSA-6hmw-9432-67qq
Shorter items
- AgenticSeek (CVE-2026-115727, 9.2).
llm_server/app.pyhardcodes Flask debug mode while binding to all interfaces; an attacker who can reach the port and derive the Werkzeug debugger PIN runs code with the server’s privileges. Fix is commit 409840c; the advisory lists no released version and is unreviewed. Check whether any self-hosted agent app of yours starts a development server in production. GHSA-r5cp-9ffr-m5mf - req_llm (CVE-2026-107685, 9.1). The Elixir LLM client’s WebSocket paths for OpenAI Responses, Realtime and Codex started without TLS options, and an allowlist dropped caller-supplied CA settings, so an on-path attacker could read the bearer token and edit sessions. HTTP paths were fine. Upgrade to 1.29.0 or later. GHSA-w53j-6pxf-r2vw
- Goose (CVE-2026-111079, 7.4). With terminal integration enabled, shell command history goes unredacted to the configured model endpoint. Affected and fixed versions are not stated (unreviewed advisory); until you can confirm a fix, switch the feature off on machines where people type secrets. GHSA-4537-c6fq-qchm
- MLflow (CVE-2026-115886, 6.5). An unauthenticated scorer endpoint can be pointed, through optional TruLens packages, at an arbitrary host, giving SSRF to metadata services. Upgrade to 3.17.0 and do not expose the tracking server without authentication. GHSA-2wqp-q3c6-ccj5
MCP and protocol security
Protocol pivoting: the same SSRF class in five MCP servers
Search extracts of secondary reports (The Next Web, Unite.AI, SecNews) say independent researcher Syed Anas Mohiuddin reported one bug class, server-side request forgery in an MCP server that builds an outbound request from a URL, path or endpoint the agent supplies, to Google, JPMorgan Chase, Weaviate, France’s DINUM and the Tangerang city government, and that each fixed it, in a follow-up titled “Protocol Pivoting, four months later”. The same reports describe a related agent-to-agent chain in which text planted in a tool result becomes a task for a subagent that trusts its orchestrator, and say he presented at MCPCon North America on 23 October. They also say some US federal MCP servers have open findings. I could not open these pages; the one GitHub advisory I found that may be related (GHSA-3x3x-8ffg-ghcv, CVE-2026-14540, an SSRF in a “generic HTTP source and tool”, dated 31 Jul) is unreviewed and does not name the product, so I do not tie it to a vendor.
Why it matters, and what to do. Whatever the attribution, the class is real and already covered in earlier reports: an MCP tool that fetches a URL is an SSRF primitive controlled by whoever can steer the agent. Resolve and validate destinations after DNS resolution, deny link-local and private ranges, and run fetch tools in a network segment with no route to metadata services. Tag early; confirm against the researcher’s write-up before citing figures.
Sources: The Next Web (search extract only) · GHSA-3x3x-8ffg-ghcv
Research
No new cs.CR paper reached the quality bar in the window; search returned papers from June and July (a 247-paper survey and an agent-versus-agent red-teaming paper) that are outside the window and add nothing new. Today’s most useful reading is the obsidian-tc advisory text, which states the limit of client-driven approval plainly.
Tools and industry
Certificate trust stores in agent stacks: the eMudhra intermediates
Search extracts of press and vendor notices say a researcher found on 17 October that private keys for eight eMudhra intermediate CA certificates (six for websites, two for code signing) could be recovered from public certificate data; Apple blocked them on 19 October, Microsoft on 20 October, and Google plans to remove the root from Chrome devices on 27 October, with no confirmed misuse by 21 October. For agent stacks, the primary evidence is FastMCP: its 4.1.3 and 3.4.11 releases (20 Oct) require certifi 2026.10.19 or later and say “upgrading FastMCP alone is insufficient” because FastMCP 4 uses system trust by default, so operating system, container and custom trust stores need updating too.
Why it matters. An agent that fetches tools and web content over TLS inherits its trust store; a rogue certificate from a trusted CA lets an on-path attacker impersonate an MCP server or model provider. This is generic IT risk with an agentic multiplier (long-lived containers, baked images). Action: rebuild images with an updated ca-certificates and certifi; check that pinned images in agent runners are not months old.
Sources: FastMCP releases · BleepingComputer, Veeam and Simon Willison pages (search extracts only, not opened)
Claude Code 2.1.310 and Codex 0.164.0
Claude Code 2.1.310 (23 Oct) closes a Windows hook gap (PreToolUse and PermissionRequest hooks letting a call through when Git Bash is missing and the command is only quoted strings), shows where a symlink leads in read-permission prompts, and tells the model not to repeat an MCP call whose elicitation went unanswered in non-interactive mode. Version 2.1.307 (21 Oct) added a claude_code.safety_event telemetry event for each call a rule, hook or sandbox stopped, which is useful for detection. Codex 0.164.0 (23 Oct) hardens sandbox checks for case-variant metadata paths and replaceable symlinks, extends credential masking, and requires fresh Guardian approval for escalated retries. Both continue the permission-layer pattern from 23 Oct. Action: update coding agents on shared runners and forward safety_event into your SIEM.
Sources: Claude Code releases · Codex releases
Policy
Nothing new in the window. Background that remains open: the US Senate “Rogue AI” hearing on 30 September and the AI Agent Accountability Act introduced on 1 October, both reported only by secondary sources, and OpenAI’s August technical report on the Hugging Face incident. The EU Digital Omnibus provisional agreement on delaying high-risk AI Act obligations is reported as adopted by the Parliament in June; I could not confirm publication in the Official Journal.
Coverage notes
The agentic-software CVE feed gained entries for obsidian-tc, Strands Agents, LangGraph’s stores, AgenticSeek, req_llm and Goose. FastMCP’s two advisories have no CVE, so they are not in the feed. MLflow is in the table but not the feed, since it is an ML platform and the flaw sits in an optional integration.