Version / branch / commit
main at commit 3c81fea
OS and environment
macOS 26.5.2 / darwin arm64 / Go 1.26.4
Summary
A user-level MCP disable can be overridden by project config. If the user disables an MCP server in their user config, a repository's project config can set the same server to disabled: false and cause it to be active again when Zero resolves MCP servers for that workspace.
This is a trust-boundary issue because zero mcp disable <server> looks like an operator/user-level opt-out, but a cloned repo can reverse that choice in .zero/config.json.
Steps to reproduce
- User config disables a default MCP server:
{
"mcp": {
"servers": {
"firecrawl": { "disabled": true }
}
}
}
- Project config in the workspace re-enables the same server:
{
"mcp": {
"servers": {
"firecrawl": { "disabled": false }
}
}
}
- Resolve MCP config for that workspace.
I verified this locally with a temporary regression test against config.ResolveMCP: the resolved firecrawl server has Disabled == false.
Expected behavior
A project config should not be able to re-enable an MCP server that the user explicitly disabled in user config. User-level disable should be sticky/authoritative unless the user re-enables it from user scope or via an explicit command/flag.
Actual behavior
Project config wins during MCP server merging. mergeMCPServer applies disabled:false when the later layer sets the disabled field, so the resolved MCP server becomes enabled again.
Relevant code/tests:
internal/config/resolver.go merges user and project MCP config in order.
internal/config/resolver.go / mergeMCPServer applies next.disabledSet and assigns base.Disabled = next.Disabled.
internal/config/resolver_test.go currently has a test showing project config can clear and re-enable a disabled MCP server.
Impact
A repo can restore a network MCP server or stdio MCP server that the user had intentionally disabled. For default/network MCP servers this can re-enable outbound connections; for stdio MCP servers this can restore startup-time process execution for a server the user opted out of.
I did not find an existing issue or open PR covering this exact user-disable override behavior.
Version / branch / commit
main at commit
3c81feaOS and environment
macOS 26.5.2 / darwin arm64 / Go 1.26.4
Summary
A user-level MCP disable can be overridden by project config. If the user disables an MCP server in their user config, a repository's project config can set the same server to
disabled: falseand cause it to be active again when Zero resolves MCP servers for that workspace.This is a trust-boundary issue because
zero mcp disable <server>looks like an operator/user-level opt-out, but a cloned repo can reverse that choice in.zero/config.json.Steps to reproduce
{ "mcp": { "servers": { "firecrawl": { "disabled": true } } } }{ "mcp": { "servers": { "firecrawl": { "disabled": false } } } }I verified this locally with a temporary regression test against
config.ResolveMCP: the resolvedfirecrawlserver hasDisabled == false.Expected behavior
A project config should not be able to re-enable an MCP server that the user explicitly disabled in user config. User-level disable should be sticky/authoritative unless the user re-enables it from user scope or via an explicit command/flag.
Actual behavior
Project config wins during MCP server merging.
mergeMCPServerappliesdisabled:falsewhen the later layer sets the disabled field, so the resolved MCP server becomes enabled again.Relevant code/tests:
internal/config/resolver.gomerges user and project MCP config in order.internal/config/resolver.go/mergeMCPServerappliesnext.disabledSetand assignsbase.Disabled = next.Disabled.internal/config/resolver_test.gocurrently has a test showing project config can clear and re-enable a disabled MCP server.Impact
A repo can restore a network MCP server or stdio MCP server that the user had intentionally disabled. For default/network MCP servers this can re-enable outbound connections; for stdio MCP servers this can restore startup-time process execution for a server the user opted out of.
I did not find an existing issue or open PR covering this exact user-disable override behavior.