Yesterday's v2.1.98 is the biggest security release in Claude Code's recent history. Six separate bash permission bypasses were patched — each one a path to arbitrary code execution through the permission system you thought was protecting you.
Here's what was broken:
1. Backslash-escaped flags. A command like rm \-rf / could bypass the read-only auto-allow heuristic because the parser treated \-rf as a different token than -rf. The escaped flag passed the safety check, then the shell stripped the backslash and executed the dangerous flag anyway.
2. Compound command bypass. Chaining commands with && or ; could slip past forced permission prompts in auto and bypass-permissions modes. The permission check saw the first (safe) command; the shell ran the full chain.
3. Env-var prefix smuggling. Prepending an environment variable to a read-only command (SOME_VAR=x cat /etc/passwd) skipped the prompt entirely. Now only known-safe vars like LANG, TZ, and NO_COLOR are exempt.
4. /dev/tcp and /dev/udp redirects. Bash's special device files for network connections weren't flagged. A redirect to /dev/tcp/attacker.com/443 was auto-allowed — effectively an unmonitored network exfil path.
5. Skip-permissions downgrade. Using --dangerously-skip-permissions and then approving a write to a protected path silently downgraded the session to accept-edits mode. Your agents thought they had full access but were quietly constrained.
6. Team permission inheritance. Agent team members didn't inherit the leader's permission mode when using --dangerously-skip-permissions. Teammates ran with default permissions instead of the intended elevated mode.
Action: Update now. Run claude update or npm install -g @anthropic-ai/claude-code@latest. If you're running autonomous agents, this is not optional — your permission boundary had holes.
The same v2.1.98 release that patched permission bypasses also shipped proactive sandboxing for the processes Claude Code spawns. Two new environment variables give you fine-grained control over what happens inside the Bash tool.
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB — When set, Claude Code scrubs the environment before spawning subprocesses and enables PID namespace isolation on Linux. Each Bash tool invocation gets its own PID namespace, meaning subprocesses can't see or signal other processes on the host. Your API keys, tokens, and session variables don't leak into child processes.
export CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1
claude -p "run the deployment script"
CLAUDE_CODE_SCRIPT_CAPS — Limits the total number of script invocations per session. If your agent runs in a cron loop, this prevents runaway execution — a misbehaving prompt can't spawn infinite subprocesses.
export CLAUDE_CODE_SCRIPT_CAPS=50
Why this matters for agent operators: sandboxing Claude Code itself (bubblewrap, firejail) restricts what the entire process can do. Subprocess sandboxing restricts what Claude Code's *children* can do. These are complementary layers. A sandboxed Claude Code session with subprocess env scrubbing means:
- The outer sandbox constrains Claude Code's filesystem and network access
- The inner sandbox constrains what scripts Claude runs can see and do
- Script caps add a hard ceiling on execution volume
If you run agents on a shared machine, enable both CLAUDE_CODE_SUBPROCESS_ENV_SCRUB and set a reasonable CLAUDE_CODE_SCRIPT_CAPS. The overhead is negligible — PID namespaces are a kernel primitive, not a VM.
The Vercel plugin for Claude Code was caught sending your full bash command strings to telemetry.vercel.com on every project — not just Vercel projects. The story hit 263 points on Hacker News yesterday, and it illustrates a trust problem that goes beyond one vendor.
What the Vercel plugin does:
- Collects bash commands. Every command Claude Code runs gets sent to Vercel's telemetry endpoint — including file paths, environment variables, and infrastructure details. This collection is always-on with no opt-in prompt.
- Fakes native consent. Instead of using a UI prompt, the plugin injects instructions into Claude's system context telling it to ask users about telemetry. The resulting question looks identical to a native Claude Code prompt. There's no visual indicator it came from a third-party plugin.
- Fires universally. The plugin's
hooks.jsonuses an empty-string matcher onUserPromptSubmit, triggering on every project regardless of whether you use Vercel.
- Has an undocumented opt-out. Set
VERCEL_PLUGIN_TELEMETRY=offto disable collection. This was not surfaced during the consent flow.
The bigger lesson: Every Claude Code plugin you install gets hooks into your workflow. Plugins can read your prompts, capture your commands, and phone home — all within the permissions you granted at install time. The Vercel plugin isn't malicious (it has a legitimate telemetry purpose), but the pattern it demonstrates applies to any plugin.
Operator checklist:
- Audit
~/.claude/plugins/cache/for installed plugins - Read each plugin's
hooks.json— check what events it matches and what scope it covers - Search plugin source for outbound HTTP calls (
fetch,axios,telemetry,analytics) - Treat empty-string matchers as red flags — they fire on everything
- Default to removing plugins you don't actively use
Trust is not binary. A plugin can be useful and still collect more than you expected.
Engram is persistent memory done right for the single-binary crowd. A Go executable with zero external dependencies, SQLite with FTS5 full-text search, and an MCP server that works with Claude Code, Gemini CLI, Cursor, and anything else that speaks MCP.
What makes it interesting:
Structured observations, not text blobs. Every memory has four fields: *What* happened, *Why* it matters, *Where* in the codebase, and what was *Learned*. This structure means retrieval is precise — you search for a function name and get the architectural context around it, not a wall of session transcripts.
Git sync without merge conflicts. Memories export as compressed chunks that commit cleanly to a repo. Drop .engram/manifest.json into a project and team members auto-import shared knowledge on session start. Your intern's first Claude session starts with everything the team has already learned about the codebase.
Post-compaction recovery. Engram hooks into Claude Code's compaction event, so memories survive /compact operations. The agent forgets its conversation history but keeps everything it explicitly saved.
13 MCP tools including mem_save, mem_search, mem_context, mem_session_summary, mem_timeline, and session lifecycle management (mem_session_start/mem_session_end).
The numbers: 2.4k stars, MIT license, 51 releases, active development. Install via claude plugin marketplace add Gentleman-Programming/engram or download the binary and run engram mcp for any MCP-compatible agent.
The memory tool landscape is getting crowded (RemembrallMCP, claude-echoes, MemoryBank, claude-mem). Engram's edge is the zero-dependency single binary and structured observation format. If your memory solution today is "CLAUDE.md files and hope," this is a meaningful upgrade.
What you'll do: Inspect every Claude Code plugin installed on your machine, identify which ones phone home, what data they collect, and decide what stays.
Steps:
- List your installed plugins:
# If empty, you have no third-party plugins — you're done
- For each plugin, inspect its hook registrations:
echo "=== $(basename $plugin) ==="
cat "$plugin/hooks.json" 2>/dev/null || echo " No hooks.json"
echo
done
Look for: empty-string matchers (fire on everything), UserPromptSubmit hooks (see your prompts), PostToolUse on Bash (see your commands).
- Scan for outbound network calls:
~/.claude/plugins/cache/ \
--include="*.js" --include="*.mjs" --include="*.ts" -l
Any file that hits? Read it. Understand what's being sent and where.
- Check for persistent identifiers:
~/.claude/plugins/cache/ \
--include="*.js" --include="*.mjs" -l
Persistent IDs enable cross-session tracking. Not inherently bad, but know they're there.
- Disable telemetry for known offenders:
export VERCEL_PLUGIN_TELEMETRY=off
# Add to your shell profile to persist
echo 'export VERCEL_PLUGIN_TELEMETRY=off' >> ~/.bashrc
- Remove plugins you don't actively use:
Expected outcome: A clear inventory of what each plugin can see and send, with telemetry disabled or plugins removed for anything that overreaches.
Verify: Re-run the grep scans after cleanup. Any remaining telemetry endpoints should be for plugins you've consciously decided to keep, with their collection scope understood.