Skip to content

fix(client): don't refuse the daemon when launch path != resolved image path (WinGet)#462

Merged
githubrobbi merged 1 commit into
mainfrom
fix/daemon-identity-launch-vs-image-path
Jun 19, 2026
Merged

fix(client): don't refuse the daemon when launch path != resolved image path (WinGet)#462
githubrobbi merged 1 commit into
mainfrom
fix/daemon-identity-launch-vs-image-path

Conversation

@githubrobbi

Copy link
Copy Markdown
Collaborator

Symptom

On a WinGet install, every uffs <search> fails:

Error: Failed to connect to UFFS daemon
  Caused by: Daemon identity verification failed … the process on the IPC
  endpoint does not match the exe hash recorded when the daemon started …

Searches are completely blocked.

Root cause

The identity check compares FNV-1a hashes of two path strings from different APIs:

side API yields
daemon (records) std::env::current_exe() the launch path
client (checks) QueryFullProcessImageNameW(pid) the resolved image path

For a normal launch these match. But WinGet exposes the binary through a shim/symlink at …\Local\Microsoft\WinGet\Links\uffsd.exe, so the daemon records the Links path while the client reads the resolved Packages path — same binary, different strings → hash mismatch → the strict check hard-refused the connection as a suspected hijack. False positive.

Fix

Make the path-string hash a fast-path, not the sole authority. On mismatch, defer to verify_daemon_identity(pid) — the peer must be a uffsd binary (by name) and pass Authenticode when signed. A genuine impostor fails that exactly as it failed the hash, so the security property is preserved; this only stops punishing a legitimate daemon for a path-representation difference. (Mirrors the existing hash == 0 fallback.)

Tests

The two strict-verify tests still pass — their non-uffsd test process is refused by the name-check fallback, so impersonation is still caught. 204 uffs-client tests green, clippy clean.

🤖 Generated with Claude Code

… image path

`uffs <anything>` failed with "Daemon identity verification failed … the
process on the IPC endpoint does not match the exe hash recorded when the
daemon started" on WinGet installs — blocking every search.

Root cause: the identity check compares FNV-1a hashes of two path STRINGS
produced by different APIs:
  - daemon records `std::env::current_exe()`        (the LAUNCH path)
  - client reads `QueryFullProcessImageNameW(pid)`  (the resolved IMAGE path)
For a daemon launched through a symlink/shim — e.g. WinGet's
`…\Local\Microsoft\WinGet\Links\uffsd.exe` — those two strings differ for the
SAME binary, so the hashes mismatch and the strict check hard-refused the
connection. It's a false positive, not impersonation.

Fix: treat the path-string hash as a fast-path, not the sole authority. On
mismatch, defer to `verify_daemon_identity(pid)` — the peer must be a `uffsd`
binary (by name) and, when signed, pass Authenticode. A genuine impostor
fails that exactly as it failed the hash, so security is preserved; this just
mirrors the existing hash==0 fallback. The two strict-verify tests still pass
(their non-`uffsd` test process is refused by the name check).

Verified: 204 uffs-client tests green, clippy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@githubrobbi githubrobbi enabled auto-merge (squash) June 19, 2026 14:59
@githubrobbi githubrobbi merged commit 3b2d559 into main Jun 19, 2026
21 checks passed
@githubrobbi githubrobbi deleted the fix/daemon-identity-launch-vs-image-path branch June 19, 2026 15:13
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