Repository navigation
fix(claude): reject non-regular Desktop configuration reads #7036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| # Claude Desktop Configuration Reads | ||
|
|
||
| Every read of Desktop library configuration — selected-profile inspection, `_meta.json` parsing, | ||
| foreign-key preservation during writes, refresh mode re-resolution, the refresh fingerprint hash, | ||
| the picker profile's inspection and apply snapshots, and the connection-owned store's metadata and | ||
| profile reads — goes through the shared verified regular-file reader in | ||
| `src/claude/desktop-3p-library.ts` (`readDesktopLibraryBytes`/`readDesktopLibraryText`). The path | ||
|
Comment on lines
+3
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
During a normal (non-refresh) rewrite of an existing profile, this “every read” claim is false: after AGENTS.md reference: structure/AGENTS.md:L9-L10 Useful? React with 👍 / 👎. |
||
| `lstat` must already name a regular file; on POSIX the open is nonblocking and no-follow, so a path | ||
| swapped to a FIFO cannot turn an observation into a blocking read and a swapped symlink is not | ||
| followed; the opened descriptor must still be a regular file whose bigint device, inode and change | ||
| time match the path observation before its bytes are read, and it is always closed. Windows keeps | ||
| the same path-and-descriptor identity check without the POSIX-only open flags. A non-regular or | ||
| swapped path throws `desktop_config_not_regular`, including a swap that surfaces only at open (a | ||
| symlink's `ELOOP`, a socket's `ENXIO`, a deletion's `ENOENT`): the failed open re-observes the path | ||
| and reports the documented refusal whenever it no longer names the expected file, while a same-path | ||
| failure keeps its own errno. Inspection reports the refusal through its existing | ||
| `metadata_unreadable`/`broken` outcomes and the writer through its existing refusals; `StoreIO.read` | ||
| in `src/claude/desktop-remote-store-io.ts` layers its size cap, private-file mode and post-read | ||
| identity contract on top of the same read and reports it as `unsafe`. | ||
|
|
||
| Tests: `tests/clients/desktop-3p-removal.test.ts`, `tests/clients/desktop-remote-store.test.ts`, and | ||
| `tests/claude-integration/claude-desktop-picker-profile.test.ts`. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
_meta.jsonis a dangling symlink (for example, after a linked configuration target is moved),existsSyncon the preceding line follows the missing target and returns false, so this checked read is skipped andparseMetadatareturns an empty library. A normal apply then writes a newly allocated profile and fails only whenatomicWriteFilereaches the dangling metadata link; because there was no backup, that new profile is left orphaned (and each retry can add another) instead of refusing before mutation. Uselstat/ENOENT handling for optional paths so an existing non-regular directory entry reachesdesktop_config_not_regular.Useful? React with 👍 / 👎.