Skip to content

fix(installer): bypass Windows Defender ASR shim-block + migrate stale configs#346

Open
Huntehhh wants to merge 2 commits into
buildingjoshbetter:mainfrom
Huntehhh:fix/windows-asr-trampoline-bypass
Open

fix(installer): bypass Windows Defender ASR shim-block + migrate stale configs#346
Huntehhh wants to merge 2 commits into
buildingjoshbetter:mainfrom
Huntehhh:fix/windows-asr-trampoline-bypass

Conversation

@Huntehhh
Copy link
Copy Markdown
Contributor

@Huntehhh Huntehhh commented May 16, 2026

Summary

Microsoft Defender's Attack-Surface-Reduction rule 01443614-cd74-433a-b99e-2ecdc07bfc25 ("Block executable files from running unless they meet a prevalence, age, or trusted list criteria") silently kills the truememory-mcp / truememory-ingest console-script shims at CreateProcess time on hardened Windows-11 dev-box configurations: those shims are setuptools / uv trampolines with a per-install unique SHA-256, so they fail the MS cloud-prevalence check before any user code runs.

The rule defaults to Audit under DISA STIG / CIS Benchmark / MS Standard Protection sets, so most users never see this — but a growing share of Win11 hardened-baseline images flip it to Block, at which point irm ... | iex of the installer dies silently at step 4, and the Claude Code / Claude Desktop MCP server config registered by _setup_claude keeps pointing at the blocked shim on every subsequent Claude launch.

This PR fixes both code paths and migrates existing stale configs forward.

What changed

Installer (install.ps1, install.sh)

  • Replace truememory-mcp --setup / truememory-ingest install invocations with $toolPython -m truememory.mcp_server --setup / $toolPython -m truememory.ingest.cli install. Routes through the high-prevalence PSF-signed python.exe, invisible to ASR. Same form _setup_claude already writes into the Claude MCP config — installer and runtime are now consistent.
  • Hoist $toolPython resolution above step 4 so both setup and model pre-download use it.
  • Soften the missing-$toolPython case to a Warn (with actionable re-run hint) instead of Die — preserves TRUEMEMORY_SKIP_SETUP=1 semantics and matches the original model-download fallback.
  • Installer footer + README "Windows: hardened ASR baselines" section: explicit Block-mode escape hatch.
  • install.sh: add set -o pipefail (mid-pipeline failures were previously silently swallowed).
  • install.ps1: quote $PKG_SPEC (TRUEMEMORY_SOURCE paths with spaces); surface uv tool uninstall exit codes > 1.

mcp_server._setup_claude — auto-migrate stale shim paths

  • New _is_shim_path() detects setuptools / uv truememory-mcp shim command paths in existing Claude Code / Claude Desktop configs (suffix matches plus canonical install-dir substrings, OS-agnostic).
  • When such a path is found, the registration is removed and re-added with the [python_path, "-m", "truememory.mcp_server"] form. Previously the "existing config preserved" branch kept ASR-blocked shim paths in place, so every Claude launch tried to CreateProcess the blocked binary. Migration is reported as "migrated from shim to python -m form" in the setup output.
  • Two remaining stdout error prints in _setup_claude routed to sys.stderr for MCP-stdio-protocol safety.

README.md

  • Step 4 Windows quit instruction: clicking X minimizes to system tray; the MCP config only reloads on a full process launch. Direct users to system-tray → Quit.
  • BibTeX citation version: 0.6.00.6.8 (matches pyproject.toml).

CHANGELOG.md: full [Unreleased] / Fixed entries.

Commits

  1. fix(installer): route through python.exe to bypass Windows Defender ASR — the core ASR fix in install.ps1 / install.sh + README + CHANGELOG (4 files).
  2. fix(installer,setup): bundle ASR-adjacent install hardening + shim-path migration — install hardening + _setup_claude migration (5 files).

Why bundle these together

All five changes target the same Windows ASR concern from different angles. The installer fix alone helps fresh installs but doesn't unblock users whose Claude MCP config already points at a shim — the migration handles those. The set -o pipefail / $PKG_SPEC / uv tool uninstall exit-code fixes were turned up by review while we were already in the install scripts; they're small and don't multiply review surface area meaningfully.

What I deliberately did NOT bundle

Saved as follow-up PRs to keep this one focused:

  • Windows subprocess portabilitystart_new_session=True raises ValueError on Windows in mcp_server.py:1181 and session_start.py:233; hooks/core.py ps/pgrep calls need Windows guards; model_client.py / model_server.py AF_UNIX sockets need fallbacks for older Win10 builds. Different mechanism, different files.
  • MCP setup hygiene — atomic settings.json writes, timestamped CLAUDE.md.bak, broader stderr routing, _path_exists("") parse-miss handling. Same area but runtime-behavior changes worth independent review.
  • Tests + Windows CItests/test_cli_help.py has two tests that invoke the bare shim and will ASR-block on Windows runners; .github/workflows/ci.yml has no Windows matrix entry.
  • Docs Windows calloutsdocs/cli.md, docs/guides/getting-started.md, docs/guides/debugging.md, docs/setup-*.md all document bare shim commands without the Windows alternative.

Review

Four-reviewer pass before opening: 2× Kosmos-Sonnet sub-agents (ASR/Windows angle + install/setup QoL angle) and PAL orchestrator with Gemini 3.1 Pro and Grok 4.3. All four agreed the install + setup changes are correct and tightly scoped. The four follow-up items above are their consensus deferral.

Test plan

  • Linux: ./install.sh succeeds end-to-end, MCP server registered with python -m truememory.mcp_server form (check ~/.claude.json or claude mcp list)
  • macOS: same as Linux
  • Windows (Audit-mode ASR, the common case): install.ps1 succeeds end-to-end, no ASR notifications
  • Windows (Block-mode ASR): install.ps1 no longer dies at step 4; MCP setup completes via python -m form
  • Existing Windows user with stale shim path in claude_desktop_config.json: running python -m truememory.mcp_server --setup reports "migrated from shim to python -m form" and the JSON gets rewritten with python.exe as the command
  • TRUEMEMORY_SKIP_SETUP=1 sh install.sh — installer skips step 4 without dying
  • install.sh with a deliberate mid-pipeline failure (e.g. unreachable mirror for curl) — installer exits non-zero, doesn't print "Installed successfully"

Merge ordering

Blocks: #348 (agent-C MCP setup hygiene) layers _path_exists("") parse-miss guard + stderr routing on top of this PR's shim-migration logic in mcp_server.py:1280-1400. Should merge in this order: #346#348.

No upstream deps — can ship anytime relative to #344 / #345 / #347 / #349 / #351 / #352 / #353 (different files or different regions of mcp_server.py). Per coordination registry recommended merge order: lands after #344 + #345 (foundational) and before #348.

Recommended merge sequence: #353 (CI) → #344 → #345 → #346 (this) → #351 → #348 → #347 → #352 → #349 → #350.

Huntehhh and others added 2 commits May 16, 2026 17:44
install.ps1 and install.sh invoked `truememory-mcp --setup` and
`truememory-ingest install` directly. On Windows hosts running Defender's
Attack-Surface-Reduction rule 01443614 in Block mode, those console-
script shims (setuptools / uv trampolines with per-install unique
hashes) silently fail the cloud-prevalence check and never launch.

Switched both installers to `\$toolPython -m truememory.mcp_server` /
`\$toolPython -m truememory.ingest.cli`, routing through the high-
prevalence signed python.exe — invisible to ASR. This mirrors the
invocation form `mcp_server._setup_claude` already writes into the
Claude Code / Claude Desktop MCP config, so installer and runtime are
now consistent.

Added a Windows-ASR troubleshooting note to the install.ps1 footer and
to the README's advanced-setup section so Block-mode users have the
manual re-run command.

Co-Authored-By: claude-opus-4-7 <wontreply@getfucked.ai>
…th migration

Bundles install-script hardening and a one-time _setup_claude shim-path
migration with the ASR fix so users with stale Claude MCP configs from
prior installs get auto-migrated to the python -m form.

install.ps1 / install.sh
- Soften the early Die-on-missing-toolPython to a Warn so
  TRUEMEMORY_SKIP_SETUP=1 (and the model-download fallback) still work
- install.sh: add `set -o pipefail` so mid-pipeline failures aren't
  silently swallowed (currently the script reports "installed
  successfully" on a broken install)
- install.ps1: quote $PKG_SPEC so TRUEMEMORY_SOURCE paths with spaces
  don't get split by PowerShell's argument parser
- install.ps1: surface `uv tool uninstall` exit codes > 1 (locked
  files, permissions) instead of swallowing them with `*> $null`
- install.ps1 footer: add a Block-mode ASR hint with the python -m
  equivalent commands so users who copy-paste the bare-shim commands
  have an escape hatch

truememory/mcp_server.py: _setup_claude
- New _is_shim_path() detects setuptools / uv truememory-mcp shim
  command paths in existing Claude Code / Claude Desktop configs
- When such a path is found, migrate the registration to the
  [python_path, "-m", "truememory.mcp_server"] form instead of
  preserving it (the previous "existing config preserved" branch left
  ASR-blocked shim paths in place — every Claude launch then tried to
  CreateProcess the blocked binary)
- Migration is reported as "migrated from shim to python -m form" in
  the setup output so the change is visible
- Route the two remaining stdout error prints in _setup_claude to
  stderr for MCP-stdio-protocol safety

README.md
- Step 4: clarify Windows "quit" — clicking X minimizes to system
  tray, MCP config only reloads at a full process launch
- BibTeX citation version: 0.6.0 -> 0.6.8

CHANGELOG.md: full Unreleased / Fixed entries for all of the above

Co-Authored-By: claude-opus-4-7 <wontreply@getfucked.ai>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant