You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CLI child processes inherit the router's whole environment, and the scrub list can be changed over the admin API #179
The CLI connectors start from the router's whole environment and remove only a short list of names for each preset:
Claude Code: ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN and ANTHROPIC_BASE_URL (CliAdapters.cs:150-151)
Codex: CODEX_API_KEY (CliAdapters.cs:324)
Copilot and Custom: nothing
Everything else reaches the child process:
other providers' keys (OPENAI_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY)
dashboard tokens and gateway keys (ROUTER_ADMIN_TOKEN, ROUTER_GATEWAY_KEY in the container, SemanticRouter__Middleware__GatewayKeys__*)
cloud credentials
SECURITY.md promises "a scrubbed environment" and lists "an API key or other variable leaking into the child" as in scope.
There is a second gap. RemoveEnvironmentVariables and PromptInput are not treated as process settings. RouterConfiguration.SameProcess and ProcessSettingChanges (src/SemanticRouter.AspNetCore/Runtime/RouterConfiguration.cs:700-737) compare only type, preset, executable, home directory, arguments and EnvironmentVariables. So an admin-API caller can change either setting without AllowProcessSettings:
Setting RemoveEnvironmentVariables: [] on the Claude Code preset brings back ANTHROPIC_API_KEY (billing switches to the API key) and ANTHROPIC_BASE_URL.
Setting PromptInput: Argument puts prompts on the command line, where other users can read them.
Evidence
src/SemanticRouter.AspNetCore/Connectors/Cli/CliProcess.cs:101-109: the remove list and then the set list are applied on top of the inherited environment.
src/SemanticRouter.AspNetCore/Connectors/Cli/CliChatConnector.cs:61: a configured list replaces the preset's defaults entirely.
docs/providers.md:199 documents only the three removed names.
Impact
The presets turn tools off, so a leak needs a CLI bug or a misconfigured Custom command. Still, any secret in the child's environment is one step from the model (a CLI's own diagnostics, a crash report, a Custom script). This is defence in depth.
Suggested fix
By default, remove every value the router itself knows to be secret: all resolved connector, embedding, gateway and dashboard secrets (by name when they came from ${env:NAME}), plus ROUTER_* and SemanticRouter__*.
Or start the child from an allow-list instead: PATH, HOME / USERPROFILE, LANG, TERM, TMPDIR and the CLI's documented configuration variables, plus EnvironmentVariables.
Make RemoveEnvironmentVariables add to the preset's defaults instead of replacing them.
Treat RemoveEnvironmentVariables and PromptInput as process settings in SameProcess.
Done when
By default, a CLI child does not see the router's other providers' keys, dashboard tokens or gateway keys. An integration test with the FakeCli checks this, as CliProcessIntegrationTests.cs:68-78 does for one variable.
Changing RemoveEnvironmentVariables or PromptInput over the admin API is refused without AllowProcessSettings, with a test.
docs/providers.md describes the child's environment.
Activity