Skip to content

Security: predictable /tmp filename in cbm-code-discovery-gate (symlink attack vector) #384

Closed

Description

@rileydev

Issue

The PreToolUse hook script cbm-code-discovery-gate (installed by codebase-memory-mcp install for Claude Code) uses a predictable filename in /tmp:

GATE=/tmp/cbm-code-discovery-gate-$PPID
find /tmp -name 'cbm-code-discovery-gate-*' -mtime +1 -delete 2>/dev/null
if [ -f "$GATE" ]; then
    exit 0
fi
touch "$GATE"

This is vulnerable to a symlink attack: an attacker who can predict $PPID (a small integer) and has write access to /tmp could pre-create a symlink at the predictable path pointing at an arbitrary target file. When the hook's touch "$GATE" runs, it would update the mtime of (or create) the target — potentially confusing other tools, or in shared environments writing into paths the user didn't intend.

The bare [ -f "$GATE" ] check also follows symlinks, so a malicious symlink would silently allow the gate to pass without the script actually creating its expected state file.

Practical risk

Low for single-user dev containers (the $PPID prediction window is narrow and /tmp typically has the sticky bit set). Higher in shared/multi-tenant environments where the script could run with predictable PPIDs alongside untrusted users.

Suggested fix

Two reasonable directions, paraphrased from an automated security review:

(a) mktemp + per-session env var:

: "${CBM_GATE_FILE:=$(mktemp -p "${XDG_RUNTIME_DIR:-/run/user/$(id -u)}" cbm-gate.XXXXXX)}"
GATE="$CBM_GATE_FILE"

(b) User-private state directory:

STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/cbm"
install -d -m 700 "$STATE_DIR"
GATE="$STATE_DIR/gate-$PPID"

Either approach, plus harden the file operations to refuse symlinks:

[ -e "$GATE" ] && [ ! -L "$GATE" ] && exit 0
install -m 600 /dev/null "$GATE"

And tighten the cleanup find to the chosen state dir rather than walking all of /tmp:

find "$STATE_DIR" -maxdepth 1 -type f -name 'gate-*' -mtime +1 -delete

Context

Found via Claude Code's automated commit security review while integrating codebase-memory-mcp v0.6.1 into a multi-agent dev container. The hook is otherwise working well and has been useful for steering agents toward MCP queries before grep — small fix, meaningful security improvement.

Happy to send a PR if helpful; flagging the issue first in case there's a preferred approach upstream.

Activity

  1. added
    bugSomething isn't working
    securitySecurity vulnerabilities, hardening
    on May 30, 2026
  2. DeusData commented on May 31, 2026

    @DeusData
    Owner

    Thank you — excellent security report, and your analysis of the symlink/PPID-prediction vector was spot on.

    The good news: this is already fixed in v0.7.0. The entire predictable-/tmp mechanism was removed in commit c29e6d5, which replaced the blocking bash gate with a non-blocking compiled augmenter. The PreToolUse hook is now a thin shim:

    #!/bin/bash
    BIN="<path-to-binary>"
    [ -x "$BIN" ] || exit 0
    "$BIN" hook-augment 2>/dev/null
    exit 0

    The augmenter (hook-augment) reads the hook JSON from stdin and writes its additionalContext payload to stdout only — it creates no temp file, no state file, and never touches /tmp or $PPID. So there is no predictable path for an attacker to pre-create a symlink against; the whole vector is gone, not just narrowed. (The dedup that the old /tmp gate provided is no longer needed — the augmenter is stateless per invocation and bounded by a 300 ms hard deadline.)

    I also added a regression guard (commit 61453e9, test cli_hook_gate_script_no_predictable_tmp_issue384) that asserts the generated shim contains no /tmp path and no $PPID, so a predictable-temp-file gate can never be reintroduced.

    Please update to v0.7.0+ and the hook will no longer write to /tmp at all. Thanks again for flagging it — closing as resolved.

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

    bugSomething isn't workingsecuritySecurity vulnerabilities, hardening

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions