voidzero-dev / voidzero-dev/vite-plus

macOS: VS Code Recent Documents can invalidate active vp inode, breaking all shims until reinstall

Open
#2,263 1 comment 1 reaction 0 assignees View on GitHub
pending triage
Dominant language
Rust
Stars
5.8k
Forks
262
Avg merge
1d 34m
Merged PRs (30d)
135

Description

### Describe the bug

On macOS, the active Vite+ Mach-O can become permanently invalid for that inode after VS Code rebuilds its Recent Documents list. Once this happens, every Vite+ shim that points to the same binary (`vp`, `node`, `nr`, `npm`, and others) is killed at exec with:

```text
SIGKILL (Code Signature Invalid)
```

Reinstalling Vite+ fixes the commands only because the new installation uses a new inode. The original file remains byte-for-byte valid and still passes `codesign --verify`, but macOS continues to reject execution from its old inode.

This incident happened immediately after `vp create`, but the evidence below shows that `vp create` did not overwrite or modify the binary. The invalidation happened after `code .`, while VS Code/CoreServices was rebuilding bookmarks for Vite+ paths stored in Application Recent Documents.

Why this is actionable in Vite+:

- All Unix shims resolve to one active, ad-hoc/linker-signed `vp` Mach-O, so one invalidated vnode breaks the whole managed runtime.
- There is no non-Mach-O launcher or recovery path capable of replacing/retrying the invalid inode after exec starts failing.
- Vite+ already handles the same macOS inode/code-signature failure class for local bootstrap in #807, but not when the active vnode is invalidated externally.

Expected behavior: opening a project in VS Code, or restoring Vite+ paths from Recent Documents, must not make `vp`, `node`, and every other managed command unusable until reinstall/reboot.

I am not currently planning to submit a PR.

### Reproduction

No project repository is needed — this is a machine-level Vite+ shim failure. The observed shell sequence and preserved runtime evidence are below.

### Steps to reproduce

Observed stateful sequence:

1. Use Vite+ v0.2.4 on macOS 26.5.2 arm64.
2. Have Vite+ shim paths in VS Code's recent documents. On this machine, these had previously been opened:

```sh
code "$HOME/.vite-plus/bin/trellis"
code "$HOME/.vite-plus/bin/"
```

VS Code's persisted `com.microsoft.vscode.sfl4` resolved entries included:

```text
$HOME/.vite-plus
$HOME/.vite-plus/0.2.4
```

3. Create a library and open it:

```sh
vp create
cd fe-qualitiy-share
code .
```

4. Run any Vite+ shim:

```sh
vp --version
node -v
nr
```

5. Each process is terminated by `SIGKILL (Code Signature Invalid)`.

Important control: the same old `vp` inode executed successfully after `vp create` completed. It only became invalid during the subsequent VS Code Recent Documents rebuild.

The trigger depends on persisted VS Code/macOS Recent Documents state, so a clean-machine reproduction may first require seeding those Vite+ paths.

### System Info

The global CLI was reinstalled to recover the shell. The affected v0.2.4 binary and inode are still preserved. Current full output:

```shell
$ vp env current
Environment:
Version 24.18.0
Source lts

Tool Paths:
node /Users/jacobzha/.vite-plus/js_runtime/node/24.18.0/bin/node
npm /Users/jacobzha/.vite-plus/js_runtime/node/24.18.0/bin/npm
npx /Users/jacobzha/.vite-plus/js_runtime/node/24.18.0/bin/npx

Package Manager:
Name pnpm
Version 11.17.0
Source devEngines.packageManager
Source Path /Users/jacobzha/Documents/workspace/jacob-open-source/fe-qualitiy-share/package.json
Project Root /Users/jacobzha/Documents/workspace/jacob-open-source/fe-qualitiy-share
Bin Path /Users/jacobzha/.vite-plus/package_manager/pnpm/11.17.0/pnpm/bin/pnpm

$ vp --version
vp v0.2.6

Local vite-plus:
vite-plus v0.2.4

Tools:
vite v8.1.3
rolldown v1.1.4
vitest v4.1.10
oxfmt v0.57.0
oxlint v1.72.0
oxlint-tsgolint v0.24.0
tsdown v0.22.3

Environment:
Package manager pnpm v11.17.0
Node.js v24.18.0

$ sw_vers
ProductName: macOS
ProductVersion: 26.5.2
BuildVersion: 25F84

$ uname -m
arm64

$ code --version
1.130.0
1b6a188127eeaf9194f945eb6eb89a657e93c54c
arm64
```

Affected global runtime:

```text
vp v0.2.4
Mach-O thin arm64
UUID AE58E66B-8D3B-33C0-9AB1-F031C072C9C6
```

### Used Package Manager

pnpm

### Logs

Exact timeline:

```text
10:28:32 vp create
10:29:39 the same old vp inode still executes successfully
10:29:46 code .

10:29:48.831 Code[44880:c85e7] CFURLCreateBookmarkData
10:29:48.831 kernel[0:c85e7] Invalidated flags, old 20020003 new 20020002
10:29:48.832 Code[44880:c85e7] inserts Recent Documents item
0F6552C6-674C-43E5-9EC6-A931997E96F6

10:29:49.616 kernel load_code_signature:
embedded signature doesn't match attached signature
10:29:49.616 kernel proc 44950:
load code signature error 2 for file "vp"

10:29:50.776 the user's nr invocation fails with the same error
```

The persisted VS Code Recent Documents archive maps item `0F6552C6-674C-43E5-9EC6-A931997E96F6` to:

```text
/Users/jacobzha/.vite-plus/0.2.4
```

The kernel and VS Code entries have the same thread ID (`c85e7`). This was the only `Invalidated flags` event between 10:20 and 10:45. Every subsequent signature-load failure named `vp`.

The flags precisely show `CS_VALID` being cleared:

```text
old 0x20020003:
CS_SIGNED 0x20000000
CS_LINKER_SIGNED 0x00020000
CS_ADHOC 0x00000002
CS_VALID 0x00000001

new 0x20020002:
CS_VALID removed
```

This matches the binary:

```text
$ codesign -dvvv ~/.vite-plus/0.2.4/bin/vp
CodeDirectory v=20400 ... flags=0x20002(adhoc,linker-signed)
Signature=adhoc
```

Disk evidence:

```text
path /Users/jacobzha/.vite-plus/0.2.4/bin/vp
inode 280661373
size 8404640
birth 2026-07-16 11:50:46
mtime 2026-07-16 11:50:46
ctime 2026-07-16 11:50:46
sha256 c372d2c2da14b1e2086a4965ced59359616d885501426669c07c244c7d854273
```

The whole `~/.vite-plus/0.2.4` tree had no ctime/mtime change during the incident. `vp create` only installed pnpm under:

```text
~/.vite-plus/package_manager/pnpm/11.17.0
```

Decisive copy experiment:

```text
original old inode:
codesign --verify --deep --strict -> valid
execution -> SIGKILL / exit 137

plain cp to a new inode:
identical SHA256
identical embedded signature
codesign --verify --deep --strict -> valid
execution -> vp v0.2.4 / exit 0
```

This matches XNU behavior:

- `csvnode_invalidate_flags()` clears `CS_VALID` when a vnode may have been modified:
https://github.com/apple-oss-distributions/xnu/blob/main/bsd/kern/kern_cs.c#L494-L545
- XNU refuses to revalidate an invalidated blob and explicitly says to reboot or create a new file:
https://github.com/apple-oss-distributions/xnu/blob/main/bsd/kern/ubc_subr.c#L5586-L5591
- `load_code_signature()` emits the observed generic mismatch when an attached blob has lost `CS_VALID`:
https://github.com/apple-oss-distributions/xnu/blob/main/bsd/kern/mach_loader.c#L3565-L3581

Related Vite+ precedent:

- #807: https://github.com/voidzero-dev/vite-plus/pull/807
- Commit message: `fix: use timestamped local-dev dirs to avoid SIGKILL on macOS`
- It documents the same stale inode/code-signature mechanism for an in-place local bootstrap overwrite. v0.2.4 already contains that fix; the `vp create vite:library` call graph does not reach bootstrap, upgrade, installer, shim refresh, or any writer of the active Mach-O.

### Validations

- [x] Read the [Contributing Guidelines](https://github.com/voidzero-dev/vite-plus/blob/main/CONTRIBUTING.md).
- [x] Check that there isn't already an issue for the same bug.
- [x] Confirm this is a Vite+ issue and not an upstream issue (Vite, Vitest, tsdown, Rolldown, or Oxc).
- [x] The provided reproduction is a minimal reproducible example.

Contributor guide

Open the contributing guide

Research direction

Start with the #807 precedent and the referenced XNU code paths for vnode code-signature invalidation. Reproduce the macOS sequence using `vp create`, `code .`, and the listed shim commands, then investigate the active Mach-O and shim recovery path. Done means opening or restoring Vite+ paths in VS Code does not leave `vp`, `node`, `nr`, or other shims unusable.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, vscode
Domain
cli, operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.