Repository navigation
fix(security): refuse more credential places on send, and write output-folder files exclusively - #1234
Merged
Conversation
leemour
force-pushed
the
fix/upload-credential-paths
branch
from
October 14, 2026 21:45
84bb7f8 to
9a03dd3
Compare
…t-folder files exclusively The upload refusal list named only a few credential folders. A talked-into agent could still attach ~/.netrc, ~/.git-credentials, gh/gcloud/docker/kube tokens, Claude and Codex credentials, keyrings, browser profiles, or another WireCat app's session (SEC-48). These are added as path parts or runs of parts, every WireCat app's folders are refused, and on macOS and Windows the names compare case-insensitively. Ordinary hidden folders still send, as the 2026-10-10 ruling requires; the messages_send description now says so. Download progress and the export manifest replaced a fixed `.tmp`/`.next` name without `wx` (FIND-1299); both now go through writeSecurely, an unguessable name opened exclusively, then renamed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ommand in the refusal max-cli and tg-cli can call the shared check instead of keeping their own list. The WireCat folder holds the store's backups. Bot uploads and tg's `bot api` @path fields reach the refusal, so it names the flag alone. The parity manifest plans --allow-any-file on tg's `bot api` itself. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
leemour
force-pushed
the
fix/upload-credential-paths
branch
from
October 14, 2026 22:03
9a03dd3 to
fa79ae5
Compare
This was referenced Oct 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Task
SEC-48 (medium) and FIND-1299 (low) from the 2026-10-14 security run.
Why
~/.netrc,~/.git-credentials,~/.config/gh/hosts.yml,~/.docker/config.json,~/.kube/config,~/.claude/.credentials.json,~/.codex/auth.json, keyrings, browser cookies, or another WireCat app's session. Themessages_sendtool description still claimed hidden files are refused, which is no longer true.messages downloadprogress (download-command.ts) and the export manifest (export-folder.ts) were written to a fixed.tmp/.nextname withoutwx, inside a folder the owner chose. A link planted at that name would be written through. The ruling keeps exclusive temporary writes.What
refusedPlace(src/sends/upload.ts) refuses these places:.netrc,_netrc,.git-credentials,.azure,.kube,.password-storeand.mozilla, in addition to the existing entries..config/{git/credentials,gh,gcloud,google-chrome,chromium,microsoft-edge,BraveSoftware},.docker/config.json,.claude/.credentials.json,.codex/auth.json,.local/share/keyrings,Library/{Keychains,Cookies,Safari}, the macOSApplication Supportfolders of Chrome, Chromium, Edge, Brave and Firefox, the WindowsAppDatafolders of Chrome, Chromium, Edge, Brave and Firefox,Microsoft/{Credentials,Protect}, andAppData/Roaming/{gcloud,GitHub CLI}.max-cli,tg-cli,cli-memo,drive-cli,zm(zoom), and the legacycli-messagingandcli-common. Each respects its<PREFIX>_*_DIRoverrides.wirecatDirectory: the store, its backups, the models) is refused as a whole, as max-cli's own list did.refusedPlaceis exported from@wirecat/cli-core/sends, so max-cli can drop its duplicate list and call this one.--allow-any-filebut no command, becausemax bot uploads putand tg'sbot api@path fields reach it too.parity.jsonplans--allow-any-fileonbot apiitself for tg (today it is on each of the 33 file-carrying operations). The row isin: []with aplannednote, so neither CLI's parity check changes until tg adopts it.darwinandwin32, names and folders compare case-insensitively.refusedPlacetakes an optionalplatformargument for this..worktrees,.cache,.incoming,.config/nvim,.docker/daemon.json,.claude/settings.json,.codex/config.tomland.local/share/fonts.messages_senddescription now names what is refused and says other hidden files are sent. The refusal messages are reworded to match.writeSecurely, which writes an unguessable temp name withflag: "wx", then renames.--allow-any-filehelp text still says "this CLI's own folders". Rewording it would also need the generated docs regenerated in max and tg; it is not wrong, only incomplete.Testing
upload.test.ts: one case per new entry (32 entries), a test that every other WireCat app's folders are refused, a test that.SSH,.Netrc,.ENV,.Config/GHand the app's ownSTATEfolder are refused on darwin and win32 but.SSHis not on linux, and the hidden-folder allow list. A test that the WireCat folder (with a store backup) is refused and a neighbour folder is not. A test that the refusal names the flag but no command.temporary-writes.test.ts: with a link planted at the old.tmp/.manifest.json.nextname, the link's target is untouched and the real file is written.pnpm typecheckandpnpm lintpass.vitest run src/services src/sends src/attachments src/mcp src/cli/messengerpasses: 1881 tests. After the rebase and the follow-ups, 580 tests insrc/sends src/attachments src/mcp src/services/attachmentsandmessenger.test.tspass. These ran with TMPDIR on /home, because the local root disk is full.Reviewed against the review checklist — §A for a docs PR, §B for code.
🤖 Generated with Claude Code