Skip to content

[Bug]: MCODE_PROVIDER_API_KEY is not stripped from bash subprocess env in scrub mode (CI) #153

Closed

Description

@KevinBarrus

Description

In scrub mode (auto-enabled when CI markers are present), the bash subprocess environment sanitizer strips well-known third-party provider keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, cloud credentials, ...), but not MCode's own BYOK key variable MCODE_PROVIDER_API_KEY. In CI, every bash command the agent runs can read the user's own provider key, while equivalent Anthropic/OpenAI keys are protected.

Source evidence

Audited against the 0.4.12 source preview (release/extraction.json sourceRevision 9b9885e42a3cf1a3df1cfa52a46e4fdb034cfcee); line numbers refer to that revision.

  • BASH_SUBPROCESS_SCRUB selection rule (comment): "the parent process needs these for API calls / lazy SDK reads, but bash subprocesses never legitimately do" — packages/agent-core/src/bash-subprocess-env.ts:66-74; the list itself at lines 75-108.
  • MCODE_PROVIDER_API_KEY is the default BYOK env var name read by the parent for provider calls: packages/tui/src/cli/provider-command.ts:54 and :106.
  • It is neither in BASH_SUBPROCESS_SCRUB nor in Layer A's runtime-boundary strip (packages/shared/src/runtime-boundary-env.ts:25-95 covers only MAVIS_* / legacy runtime identity keys).
  • Mode resolution: CI markers (CI, GITHUB_ACTIONS) auto-select scrub — packages/agent-core/src/bash-subprocess-env.ts:166-187.

By the list's own stated rule, MCODE_PROVIDER_API_KEY qualifies exactly like ANTHROPIC_API_KEY: needed by the parent per-request, never legitimately needed by a bash subprocess.

Expected behavior

In scrub (and strict) mode, the runtime's own provider key variable is withheld from bash subprocesses, consistent with the other provider keys.

Suggested fix

Add MCODE_PROVIDER_API_KEY to BASH_SUBPROCESS_SCRUB (it is already matched by SENSITIVE_ENV_NAME_RE for strict mode, so only the scrub list needs the entry).

Note: custom --api-key-env <NAME> values cannot be covered by a fixed list; the default name is what can be fixed cheaply. A host-side option to extend the scrub list with the configured key-env name would cover the custom case.

Environment

Found by source audit; not runtime-reproduced. No real credentials involved.

Activity

  1. KevinBarrus commented on Sep 18, 2026

    @KevinBarrus
    Author

    Closing for now to keep this batch of reports smaller — I kept the two highest-impact findings open (#150 permission enforcement, #152 context compaction trigger). Happy to reopen or refile if maintainers find this one useful; the analysis in the body stays valid against the cited revision.

  2. KevinBarrus commented on Sep 18, 2026

    @KevinBarrus
    Author

    Reopening — closing them added nothing since closed issues stay fully visible. Keeping all five open for triage.

  3. hetaoBackend commented on Sep 18, 2026

    @hetaoBackend
    Collaborator

    Thanks for the report. Fixed and merged in #167 (commit e3724a13d72d61c9bdc68a1a72b5c020f065ba26).

    The precise scrub list now includes MCODE_PROVIDER_API_KEY, which also removes INPUT_MCODE_PROVIDER_API_KEY. Tests cover CI-selected scrub, the spawn hook, input immutability, and preservation of off mode and the strict allowlist. Provider URL/model settings and legitimate GH/npm token behavior are unchanged.

    Custom --api-key-env names remain outside this fixed list; this change addresses the default credential name reported here.

    Validation: all 106 new regression cases pass; the full local verification profile passed on macOS arm64, and Linux/macOS/Windows CI plus the source audit passed on the PR head. Built-CLI smoke/startup and offline BYOK runtime tests also passed with synthetic credentials. This is a source fix on main; it does not imply a new package release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions