fix(mcp): restrict env var expansion in MCP configs
Block sensitive env var interpolation in MCP config expansion so repo and plugin MCP definitions cannot exfiltrate secrets by default. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -57,6 +57,7 @@ beforeEach(() => {
|
||||
spyOn(agentLoader, "loadProjectAgents" as any).mockReturnValue({})
|
||||
|
||||
spyOn(mcpLoader, "loadMcpConfigs" as any).mockResolvedValue({ servers: {} })
|
||||
spyOn(mcpLoader, "setAdditionalAllowedMcpEnvVars").mockImplementation(() => {})
|
||||
|
||||
spyOn(pluginLoader, "loadAllPluginComponents" as any).mockResolvedValue({
|
||||
commands: {},
|
||||
@@ -103,6 +104,7 @@ afterEach(() => {
|
||||
;(agentLoader.loadUserAgents as any)?.mockRestore?.()
|
||||
;(agentLoader.loadProjectAgents as any)?.mockRestore?.()
|
||||
;(mcpLoader.loadMcpConfigs as any)?.mockRestore?.()
|
||||
;(mcpLoader.setAdditionalAllowedMcpEnvVars as any)?.mockRestore?.()
|
||||
;(pluginLoader.loadAllPluginComponents as any)?.mockRestore?.()
|
||||
;(mcpModule.createBuiltinMcps as any)?.mockRestore?.()
|
||||
;(shared.log as any)?.mockRestore?.()
|
||||
@@ -173,6 +175,36 @@ describe("Sisyphus-Junior model inheritance", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("MCP env allowlist initialization", () => {
|
||||
test("sets the configured MCP env allowlist before plugin loading", async () => {
|
||||
// given
|
||||
const pluginConfig = createPluginConfig({
|
||||
mcp_env_allowlist: ["CUSTOM_API_KEY", "CUSTOM_AUTH_TOKEN"],
|
||||
})
|
||||
const config: Record<string, unknown> = {
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
agent: {},
|
||||
}
|
||||
const handler = createConfigHandler({
|
||||
ctx: { directory: "/tmp" },
|
||||
pluginConfig,
|
||||
modelCacheState: {
|
||||
anthropicContext1MEnabled: false,
|
||||
modelContextLimitsCache: new Map(),
|
||||
},
|
||||
})
|
||||
|
||||
// when
|
||||
await handler(config)
|
||||
|
||||
// then
|
||||
expect(mcpLoader.setAdditionalAllowedMcpEnvVars).toHaveBeenCalledWith([
|
||||
"CUSTOM_API_KEY",
|
||||
"CUSTOM_AUTH_TOKEN",
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
describe("Plan agent demote behavior", () => {
|
||||
test("orders core agents as sisyphus -> hephaestus -> prometheus -> atlas", async () => {
|
||||
// #given
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { OhMyOpenCodeConfig } from "../config";
|
||||
import { setAdditionalAllowedMcpEnvVars } from "../features/claude-code-mcp-loader";
|
||||
import type { ModelCacheState } from "../plugin-state";
|
||||
import { log } from "../shared";
|
||||
import { applyAgentConfig } from "./agent-config-handler";
|
||||
@@ -23,6 +24,7 @@ export function createConfigHandler(deps: ConfigHandlerDeps) {
|
||||
return async (config: Record<string, unknown>) => {
|
||||
const formatterConfig = config.formatter;
|
||||
|
||||
setAdditionalAllowedMcpEnvVars(pluginConfig.mcp_env_allowlist ?? [])
|
||||
applyProviderConfig({ config, modelCacheState });
|
||||
clearFormatterCache()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user