Skip to content

Our research

CVE-2026-114123: Missing Authentication in the D365 F&O MCP Server Explained

By Lucas Weber, CyberSec42 · Updated 28 Oct 2026

Schematic of an MCP server sitting between an AI client and a target system

CVE-2026-114123 is a missing-authentication flaw caused by an insecure default in the open-source D365 F&O MCP Server (npm package d365fo-mcp): the official Azure one-click deployment set the API key to an empty value by default, and with an empty key the server let every request through without authentication. Anyone who followed the documented steps and left the optional field blank ended up with a publicly reachable endpoint that served indexed, proprietary X++ source code and metadata from Dynamics 365 Finance & Operations. The issue is rated CVSS 7.5 (high), affects all versions up to and including 1.10.1, is fixed in 1.11.0, and was reported by CyberSec42.

In short.

Background

What the server does and what sits in its index.

Go to section

The vulnerability

The mechanism in plain terms and in detail.

Go to section

Who was affected

Versions and deployment paths.

Go to section

The fix

What changed and what operators should do.

Go to section

Timeline

Publicly documented dates only.

Go to section

The underlying pattern

Optional authentication as an insecure default.

Go to section

Key facts

ItemDetail
IdentifiersCVE-2026-114123, GHSA-8764-fh3m-wf7g
ProductD365 F&O MCP Server (dynamics365ninja/d365fo-mcp-server), npm package d365fo-mcp
ClassCWE-306 "Missing Authentication for Critical Function", CWE-1188 "Insecure Default Initialization of Resource"
SeverityCVSS 3.1: 7.5, high (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
Affectedall versions up to and including 1.10.1
Fixed1.11.0, released 13 Aug 2026
PublishedGitHub advisory on 12 Aug 2026, CVE record on 21 Oct 2026 (GitHub as CVE Numbering Authority)
CreditReported by CyberSec42 (GitHub: lwebmedia), credited as reporter on the GitHub advisory

Background: what the D365 F&O MCP Server is

The Model Context Protocol (MCP) is an open standard that lets AI assistants call tools and data sources. An MCP server receives tool calls from an AI client and answers them from a target system. According to the CVE record, the D365 F&O MCP Server is an MCP server for querying Dynamics 365 Finance & Operations X++ code and metadata. Developers use it so that an AI assistant writing X++ can rely on the real classes, tables, fields and labels of their own system.

To do that, the server builds an index: a symbol database generated from the D365 environment's PackagesLocalDirectory. The project's security policy is explicit about what it contains: X++ source snippets, extension and event-handler wiring, security roles, privileges and duties, and label text, including the organisation's own custom models and not just Microsoft's standard ones. In other words, the index is a company's proprietary business logic in machine-readable form.

The server supports two transports. With stdio, the AI client launches the server as a local process and there is no network endpoint. With the HTTP transport, the server runs as a network service and accepts JSON-RPC requests at /mcp. For HTTP operation the project's README offers a "Deploy to Azure" button that creates an Azure App Service and its configuration from an ARM/Bicep template. That path is the subject of this article. For general hardening advice, see our guide to securing MCP servers.

The vulnerability

In plain terms

Picture an archive room with a combination lock. It ships configured so that an empty combination opens the door, and the setup guide marks the combination field as "optional". Follow the guide, skip that field, and you have a door that opens for anyone standing in front of it. The archive also happens to sit on a public street.

That is how the Azure deployment of the D365 F&O MCP Server behaved up to 1.10.1. The combination is the API key; the public street is the App Service's public hostname.

Technical detail

Three pieces combined, each documented in the advisory down to file and line:

The template also hard-coded MCP_SERVER_MODE=read-only on the App Service, so write tools were not offered on this path. The read tools remained reachable, among them search, get_object_info, batch_get_info, extension_info, security_info, find_references and find_event_handlers. Several of them return the source_snippet field from the index, i.e. excerpts of X++ source. The project's security policy now states explicitly that MCP_SERVER_MODE is a tool-surface partition, not a privilege boundary: it limits which tools are reachable, not who may reach them.

Reading the vector: AV:N, PR:N and UI:N mean the attack works over the network, without credentials and without any user action. C:H denotes a high loss of confidentiality. Integrity and availability are unaffected according to the vector, because no write tools were exposed on this path. We recomputed the 7.5 base score from the formula in the CVSS 3.1 specification.

Schematic flow

Caller no API key App Service /mcp API_KEY empty Rejected key is mandatory Index X++ and metadata from 1.11.0 rejected up to 1.10.1
Up to 1.10.1, the documented one-click path produced an empty key, and the middleware let unauthenticated requests through to the read tools. From 1.11.0, the template requires a key and the server refuses to start on a public interface without authentication.
  1. An organisation deploys the server via "Deploy to Azure" and leaves the apiKey field, described as optional, empty.
  2. The App Service runs with API_KEY="" on its public HTTPS hostname.
  3. A caller who knows that hostname sends a JSON-RPC request to /mcp with no key header.
  4. The middleware sees no configured key and hands the request to the tool.
  5. The tool responds as it would to an authorised user, including source snippets from the index.

We deliberately do not publish exploit code. The description is enough to assess your own deployment and follow the fix.

How we tested

The finding comes from a source-only review of the public repository. As stated in the advisory, we did not access, scan or contact any live deployment of this software, any Azure subscription belonging to another party, or any D365 Finance & Operations environment. At no point did we execute, build or install code from the project. The flow above was traced through the source code, not against anyone's system.

Who was affected

The GitHub advisory lists the npm package d365fo-mcp in all versions up to and including 1.10.1; the CVE record phrases it as "prior to 1.11.0". Both describe the official Azure one-click deployment. The CVE record draws an explicit line: deployments protected by a configured API key, effective upstream authentication, or network restrictions that keep an attacker out are outside this scenario.

DeploymentAssessment up to 1.10.1
stdio (local process of the AI client)No HTTP endpoint; the described path does not exist
Azure one-click, apiKey empty, no network or access control of your ownAffected. Read tools reachable without authentication on the public hostname
Azure one-click with apiKey setRequests without a valid key are rejected
Own network restriction or upstream authentication (Private Endpoint, IP restriction, Easy Auth)Outside the scenario per the CVE record, provided it actually keeps an attacker from reaching the endpoint

Two further points come from the maintainer's commit messages. First, according to the maintainer's analysis, a deployment through the bundled Azure DevOps pipeline onto a hand-created App Service without API_KEY was just as exposed; the second fix commit closes that path too. Second, the commit notes that the hostname is not hard to find: it is derived from the resource group name and appears in Certificate Transparency logs.

How much risk an individual deployment carried depends on whether the key stayed empty, whether separate Azure controls were in place, and which models were in the index.

The fix and what operators should do now

What changed in 1.11.0

The fix consists of two commits that shipped in 1.11.0:

The fix is flagged as a breaking change: an existing App Service without API_KEY will not start after the upgrade. That is intentional; a silent exposure becomes a visible failure.

Recommendations for operators

The steps below are our recommendations. Where they draw on the project's own guidance, that is noted.

StepAction
1. Set a keyBefore upgrading, store a long random API_KEY in the App Service, for example from openssl rand -hex 32 as the project docs suggest. Otherwise 1.11.0 will not start.
2. UpgradeMove to 1.11.0 or later. Per the advisory, 1.10.1 is still affected.
3. AssessIf the key was empty and the App Service was reachable without a network restriction of your own, assume the index was readable from outside and assess that internally.
4. Review logsIf App Service HTTP logging was enabled, look for requests to /mcp from unknown addresses.
5. Restrict the networkPut a Private Endpoint or IP restrictions in front of the App Service if your team's addresses are known. The project's security policy recommends the same.
6. Identity over a shared keyAdd Easy Auth with Entra ID so every user has their own credentials. Rotate the shared key when someone leaves the project (also per the project's policy).

Timeline

Only dates that can be verified from public sources are listed.

DateEventSource
27 Jul 2026Version 1.5.2 released, the state reviewed in the advisorynpm registry, advisory
28 Jul 2026Advisory created in the repositoryGitHub advisory (API)
29 Jul 2026First fix commit authoredGitHub, commit e70bd05
11 Aug 2026Version 1.10.1 released, the last affected versionGitHub release, npm registry
12 Aug 2026Both fix commits on the main branch; GitHub advisory GHSA-8764-fh3m-wf7g publishedGitHub
13 Aug 2026Version 1.11.0 with the fix releasedGitHub release, npm registry
20 Oct 2026CVE ID reserved by GitHub as CNACVE record
21 Oct 2026CVE record CVE-2026-114123 publishedCVE.org, NVD

The underlying pattern: optional authentication as the default

Behind CVE-2026-114123 is a pattern common in developer tooling. Locally, a server without authentication is convenient, so authentication is optional. Once the same code ships to the cloud through a template, "optional" turns into an open internet service. It becomes dangerous when an empty secret means "check disabled" and the deployment tooling ships exactly that empty value as its default.

In our walkthrough of the OWASP MCP Top 10, the case touches two classes: missing transport authentication (class 1) and insecure defaults (class 9). For MCP server developers, four rules follow:

The flip side for operators: an MCP server with an HTTP transport is a network service with access to your data. Treat it like any other API, with authentication, network restrictions and a close look at what a one-click template actually provisions.

Thanks to the maintainer

We thank the project's maintainer (GitHub: dynamics365ninja) for the coordinated collaboration. The report was handled privately through a GitHub repository advisory. The maintainer fixed the root cause in several places rather than only changing the default, covered an additional deployment path along the way, added tests, published a security policy, requested the CVE ID from GitHub as CNA, and credited CyberSec42 as reporter on the advisory.

Is your MCP server as locked down as you think?

We test MCP servers and AI agents within a scope agreed in writing: who can reach the endpoint, what gets through without authentication, what your deployment templates actually provision, and what data a tool call returns. Every finding comes with reproducible evidence and a concrete fix. More under AI pentest & MCP security.

Request an AI pentest

CyberSec42 is an independent technical security assessment, not an accredited certification body, and does not provide legal advice. CyberSec42 is not affiliated with the D365 F&O MCP Server project or with Microsoft. Dynamics 365 is a trademark of Microsoft.

Frequently asked questions

What is CVE-2026-114123?

A missing-authentication flaw caused by an insecure default in the D365 F&O MCP Server. The official Azure one-click deployment left the API key empty by default, and with an empty key the server accepted requests without authentication. The CVE record rates it CVSS 7.5 (high).

Which versions are affected?

Per the GitHub advisory, all versions of the npm package d365fo-mcp up to and including 1.10.1. It is fixed in 1.11.0, released on 13 Aug 2026. Set an API_KEY before upgrading, or the new version will not start on the App Service.

Am I affected if I run the server locally over stdio?

In stdio mode the AI client launches the server as a local process without an HTTP endpoint, so the described path does not exist. The vulnerability is described for the Azure deployment using the HTTP transport. You should still upgrade.

Is Dynamics 365 Finance & Operations itself affected?

No. The CVE record names only the D365 F&O MCP Server. What was exposed was the data the server had indexed from your D365 environment, not the D365 environment itself. The project's security policy explicitly excludes vulnerabilities in D365 F&O.

Was the vulnerability actively exploited?

The public sources, meaning the advisory, the CVE record and the fix commits, make no statement on this. Whether your own deployment was affected can only be judged from your configuration and, where available, your logs.

Further reading

Sources