[BUG] Windows: security-guidance's sg-python.sh launches `py -3` twice per hook; each launch of the Python Install Manager alias starts an AppX update that leaks ~1.6 MB in AppXSvc, exhausting system commit (21.8 GB in 12 h)

Status Open
Reported on v2.1.287
Maintainer reply None cached
Activity 0 comments · opened Oct 2, 2026

What's Wrong?

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

The security-guidance plugin (2.0.8) runs hooks/sg-python.sh on SessionStart, every UserPromptSubmit, every PostToolUse on Edit|Write|MultiEdit|NotebookEdit, PostToolUse on Bash, every Stop and every SubagentStop. On every one of those, sg-python.sh resolves the interpreter from scratch: it launches each candidate (python3.13 … python3.10, python3, python, py -3) with -c to read its version, then launches the chosen one again to run the hook. So every hook launches Python at least twice, and more when earlier candidates fail the probe.

On Windows with python.org's Python Install Manager (the MSIX package PythonSoftwareFoundation.PythonManager), the candidate that answers in Git Bash is py -3, the package's app execution alias. Every activation of that alias makes Windows start an App Installer update in the AppX Deployment Service (AppXSvc, event 603), and each update leaves about 1.6 MB of committed memory and 5 handles in AppXSvc that are never released while it runs. That leak is a Windows defect, reported to Microsoft separately; the package's 24-hour update interval and CheckForUpdatesOnLaunch = False are both ignored.

What makes it a Claude Code problem is the rate. With five sessions open, the hooks launched py often enough for 5,980 updates between 18:26 and midnight. After 12 hours of uptime:

  • AppXSvc held 21.84 GB committed, with a 0.61 GB working set and 90,260 handles;
  • the system had 1.2 GB of 101.6 GB commit left;
  • new processes failed with OutOfMemoryException at startup while 42 GB of RAM was free, which took down unrelated .NET services and a test run.

The update events arrive in pairs within the same second, one pair per hook: the probe launch, then the run launch.

What Should Happen?

A hook should cost at most one interpreter launch, and never a launch of a Windows app alias when a real interpreter path is available:

  1. Resolve the interpreter once per session (at SessionStart), keep its absolute path, and exec that path in every later hook.
  2. When nothing is cached, check the version and run the hook in the same launch, rather than probing and then launching again.
  3. On Windows, prefer a real interpreter over anything under %LOCALAPPDATA%\Microsoft\WindowsApps. Activating an app execution alias goes through AppX activation, and with the Install Manager that started an update every time.

Error Messages/Logs

# The launcher, caught by polling Win32_Process for 40 s:
py.exe  -> C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\py.exe -3 C:/Users/<user>/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.8/hooks/security_reminder_hook.py   (parent: bash)
python.exe -> C:\Users\<user>\AppData\Local\Python\pythoncore-3.14-64\python.exe C:/Users/<user>/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.8/hooks/security_reminder_hook.py

# Microsoft-Windows-AppXDeploymentServer/Operational, event 603, once per py.exe launch, in pairs:
Started deployment UpdateUsingAppInstallerOperation operation on a package with main parameter
PythonSoftwareFoundation.PythonManager_26.3.240.0_x64__3847v3x7pw1km and Options 0 and 0.

# Counts from the same log:
2026-10-01 18:26-24:00   5,980 updates
2026-10-02 08:23-10:41   1,616 updates   (285 in one ten-minute window)

# AppXSvc between two readings, 176 updates apart:
10:23:52  2.00 GB private,  9,237 handles
10:31:06  2.28 GB private, 10,103 handles    -> ~1.6 MB and ~5 handles per update

# 12 hours after boot:
AppXSvc: private (commit) 21.84 GB; working set 0.61 GB; handles 90,260
System:  commit free 1.2 GB of 101.6 GB; RAM free 42 GB

Steps to Reproduce

  1. On Windows 11, install Python from python.org's Python Install Manager (https://www.python.org/ftp/python/pymanager/pymanager.appinstaller), so that py in Git Bash is the package's alias in %LOCALAPPDATA%\Microsoft\WindowsApps, and no python3.1x, python3 or python earlier on Git Bash's PATH answers the probe.
  2. Enable the security-guidance plugin (2.0.8) from claude-plugins-official.
  3. Use a Claude Code session normally (prompts, edits, turn ends), or run the launcher directly from Git Bash:

``bash
shim=~/.claude/plugins/cache/claude-plugins-official/security-guidance/2.0.8/hooks/sg-python.sh
for i in $(seq 100); do bash "$shim" -c pass; done
``

  1. In Event Viewer, open Applications and Services Logs › Microsoft › Windows › AppXDeploymentServer › Operational: one event 603 for PythonSoftwareFoundation.PythonManager per py launch, two per hook.
  2. Watch the private bytes and handle count of the svchost.exe hosting AppXSvc. They grow by about 1.6 MB and 5 handles per event, and fall only after a reboot or a restart of the service.

Claude Model

Not sure / Multiple models

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.287

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

  • Seen on Claude Code 2.1.278, 2.1.280, 2.1.281 and 2.1.287, so it isn't new in the current release.
  • Environment: Windows 11 Pro 25H2, build 26200.9457; Claude desktop app (MSIX) 2.19675.0.0, Code tab; hooks run through Git Bash; security-guidance 2.0.8; Python Install Manager 26.3.240.0; App Installer 1.29.379.0.
  • Workaround, verified: uninstall the Python Install Manager and install Python from python.org's standard installer. After a reboot, the same launcher ran 22 times with no update events, and AppXSvc stayed at 0.03 GB and 683 handles.
  • Related, not duplicates: anthropics/claude-plugins-official#6186 (every hook ENOENTs when python3 is an Install Manager alias), #5330 and #4894 there, and #85163 here (every Bash call registers five handlers, so five Python processes), and anthropics/claude-plugins-official#6315 (the probes have no timeout). Each of those multiplies the launches this report counts.

View original on GitHub ↗