Please do not open a public GitHub issue for a suspected vulnerability.
To report one, create a draft GitHub security advisory:
https://github.com/argoproj-labs/mcp-for-argocd/security/advisories/new
This is the same process the Argo CD project uses. The advisory is private until we publish it, and it is where a CVE is requested and the fix is coordinated. Reports sent to individual maintainers or to any vendor's support channel will be redirected here, which only delays the fix.
Please include enough detail to reproduce the issue: the affected version, the configuration or transport involved (stdio, http, sse), and the steps or proof of concept.
We will do our best to respond quickly, though a reply may occasionally take longer (for example, out-of-office periods). We are happy to coordinate a disclosure timeline with you and to credit you in the advisory.
Findings from automated scanners are already public, so report those as a normal GitHub issue — the discussion is usually of general benefit.
Fixes land on main and ship in the next release. Please confirm an issue against the latest release before reporting it.
Network Exposure covers the settings. These are the parts that tend to surprise people.
- The token gates the listener, not the caller.
MCP_AUTH_TOKENis one shared secret, not a per-caller identity. Anyone holding it can call every registered tool and, with a token registry, target any base URL in it. For different reach per caller, run separate instances, each with its own token, registry entries, and read-only mode. - A proxy or a published port changes the
Origin. The allowed loopback origins use the port the server itself binds. Through-p 8080:3000or a TLS proxy the browser sends the origin it sees, so pass that to--allowed-origin. The403echoes the value it rejected. - Non-
http(s)origins work,nulldoes not.vscode-webview://<id>andchrome-extension://<id>match as exact strings. Thenulla sandboxed orfile://context sends is refused, since allowing it would admit every such context at once. Originalone is not enough on an exposed bind. A browser omitsOriginon a same-originGET, and a DNS-rebound page believes it is same-origin.Hostvalidation is what covers that, so pass--allowed-host-headeror setMCP_AUTH_TOKEN. A proxy that forwards the client's originalHostneeds that name allow-listed too.- Browsers cannot call this server directly. It sends no CORS headers, and
MCP_AUTH_TOKENcannot be attached to anEventSource.--allowed-originonly keeps this layer from rejecting a browser client that sits behind a CORS-terminating proxy. - Token whitespace. Surrounding whitespace is stripped, since
$(cat token)and--from-filesecrets carry a trailing newline. Whitespace inside the token is a startup error, because such a token could never be sent in a header. - Bind address. All of
127.0.0.0/8counts as loopback, and IPv6 works with or without brackets. The default is IPv4 only, so a client insisting onhttp://[::1]:3000needs--bind-address ::1, or::for both stacks. - Loopback is reachable from a same-pod sidecar. A published port (
docker run -p …) is what does not reach a loopback listener; that needs an explicit wider bind.