close
Skip to content

Test scripts share the account daemon runtime and can stop active MCP sessions #1691

Description

@astandrik

Version

Originally observed with codebase-memory-mcp 0.10.2. Reproduced from source on current main at c1a5de3bda2f013b93a2beb66905de17e39a3e11 (codebase-memory-mcp dev).

Platform

macOS (Apple Silicon)

Install channel

Built from source for the reproduction. The original recurring failures used the standard binary from the GitHub release archive.

Binary variant

standard

What happened, and what did you expect?

Some test and security scripts launch the product binary without assigning a private daemon runtime. They therefore use the same account-level rendezvous as active MCP sessions.

The directly reproduced case is scripts/security-install.sh. The script creates a temporary HOME, but then runs a real install -y while inheriting the caller's daemon runtime. The install activation guard intentionally stops every client in that runtime. If make security runs while an editor or coding agent is using Codebase Memory, the test can terminate those MCP sessions.

The test should write only inside its sandbox and must not connect to, stop, or replace an account daemon used by another process.

Reproduction

This reproduction uses a private sentinel runtime, so it does not touch the normal account daemon.

git clone https://github.com/DeusData/codebase-memory-mcp.git
cd codebase-memory-mcp
git checkout c1a5de3bda2f013b93a2beb66905de17e39a3e11
make -f Makefile.cbm cbm

binary="$PWD/build/c/codebase-memory-mcp"
repro_root="$(mktemp -d /private/tmp/cbmri.XXXXXX)"
mkdir -m 700 "$repro_root/runtime" "$repro_root/cache"
export CBM_RUNTIME_DIR="$repro_root/runtime"
export CBM_CACHE_DIR="$repro_root/cache"

mkfifo "$repro_root/stdin"
exec 3<>"$repro_root/stdin"
"$binary" <&3 >"$repro_root/client.out" 2>"$repro_root/client.err" &
client_pid=$!

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"runtime-isolation-repro","version":"1.0"}}}' \
  >&3

for _ in {1..100}; do
  grep -q '"id":1' "$repro_root/client.out" && break
  sleep 0.1
done

"$binary" daemon status
scripts/security-install.sh "$binary"
"$binary" daemon status

exec 3>&-
wait "$client_pid" || true
"$binary" daemon stop >/dev/null 2>&1 || true
rm -rf "$repro_root"

Before the install audit:

daemon: active (session-managed)
  committed clients: 1

The audit then prints:

Stopping active CBM sessions and operations for install...
=== Install output audit passed ===

The MCP frontend exits with code 0 and the final status is:

daemon: not running

The daemon log records:

level=info msg=daemon.runtime_stopping reason=activation_shutdown
level=info msg=daemon.activation_shutdown action=install active_clients=1 active_connections=1

As a control, I ran the same install audit with a different CBM_RUNTIME_DIR and CBM_CACHE_DIR. The sentinel remained connected in runtime A with the same daemon PID.

Other launch sites to audit

Source inspection found the same missing runtime boundary in these product-binary test paths:

  • scripts/security-fuzz.sh sets HOME and CBM_CACHE_DIR, but not CBM_RUNTIME_DIR.
  • scripts/security-fuzz-random.sh and scripts/security-network.sh launch the binary without a private runtime.
  • tests/test_parent_watchdog.sh and tests/test_worker_watchdog.sh launch a development binary without a private runtime.
  • tests/test_worker_error_response.sh sets separate cache directories, but its CLI and daemon stop commands still share the account rendezvous.
  • scripts/test.sh invokes the watchdog and worker scripts as part of its normal full run.

Only security-install.sh is required for the reproduction above. The other paths are listed because they cross the same runtime boundary and should be covered by the fix.

Proposed fix

  1. Add a small shared test helper that creates a short, owner-only runtime parent and cache directory.
  2. Set both CBM_RUNTIME_DIR and CBM_CACHE_DIR before every test or security script launches the product binary.
  3. Isolate the standalone scripts themselves, rather than relying only on scripts/test.sh or the Makefile target, because contributors can run each script directly.
  4. Keep processes within one test in the same private runtime, but give concurrent test invocations different runtimes.
  5. Correct the security-install.sh comment that calls this a dry-run. The script currently performs a sandboxed real install, which is useful for auditing writes.

Suggested regression

Start a sentinel MCP client in runtime A, run each product-binary test entry point in runtime B, and assert that:

  • the sentinel remains connected;
  • the runtime A daemon PID and generation do not change;
  • no activation_shutdown is recorded in runtime A;
  • two concurrent security runs use separate rendezvous directories;
  • existing test exit codes and assertions are unchanged.

Logs

The relevant sanitized lines are included in the reproduction. No project indexing is required.

Diagnostics trajectory (memory / performance / leak issues)

Not applicable. This is a deterministic runtime-isolation failure, not a memory or performance issue.

Project scale (if relevant)

Not applicable.

Confirmations

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingeditor/integrationEditor compatibility and CLI integrationpriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.stability/performanceServer crashes, OOM, hangs, high CPU/memoryux/behaviorDisplay bugs, docs, adoption UX

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions