[BUG] Desktop: misbehaving DXT can spam unblockable file-attach consent dialog with no UI escape
Summary
A misbehaving DXT extension (in my case, kapture 2.1.2) can dispatch repeated synthetic "file drop" events to the Claude Desktop renderer, causing the file-attach consent dialog to fire on every app launch and view transition. The dialog has no "always deny for this source" option and no rate limit, and Cancel does not evict the offending source — so the only escape was uninstalling the extension by direct filesystem manipulation. There is no in-app path to recover while the dialog is firing.
I have filed an upstream issue at williamkapke/kapture for the proximate cause. This issue is about the defense-in-depth gap in Claude Desktop that turned a misbehaving extension into an unbootable UI.
Environment
- Claude Desktop: 1.7196.0 (Microsoft Store install)
- OS: Windows 11 Pro (10.0.26200)
- Triggering DXT: kapture 2.1.2
Evidence
%APPDATA%\Claude\logs\main.log contains, repeatedly, on every app launch and view transition:
[info] Handling file drop: C:\Users\jak36\AppData\Roaming\Claude\Claude Extensions\ant.dir.gh.williamkapke.kapture\dist\index.js
[info] LocalAgentModeSessions.setDraftSessionFolders: 0 folders
[info] setDraftSessionFolders: setting 0 folders for draft session
[info] LocalAgentModeSessions.isFolderTrusted: C:\Users\jak36\AppData\Roaming\Claude\Claude Extensions\ant.dir.gh.williamkapke.kapture\dist -> false
[info] Handling file drop: ...\kapture\dist\index.js
The drops re-fire on view transitions (Chat ↔ Cowork ↔ Code tab switches, session selection, shell PTY launches inside a Code session).
Reproduction
- Install kapture 2.1.2 as a DXT
- Launch Claude Desktop
- Observe
Attach 'index.js' to this session?dialog firing repeatedly - Cancel — it re-fires on the next view change
- Try to navigate Settings → Extensions to disable kapture — possible but painful because the dialog re-fires during navigation
Defense-in-depth improvements
- Rate-limit consent dialogs for the same
(source, file)pair. Once per session at most; ideally once ever for a "deny" choice. - Add a "Block this source" option alongside Allow / Cancel — when an extension is misbehaving, the user needs a way to say "stop asking about anything from this source."
- Treat drops with source paths inside
AppData\Roaming\Claude\Claude Extensions\as suspect. An extension dropping its own files onto the chat composer is almost never a legitimate user gesture. At minimum, suppress the consent dialog and log; ideally, refuse the drop and surface a one-time notice that the extension is misbehaving. - Re-enable DevTools in the desktop app. Ctrl+Shift+I, Ctrl+Alt+Shift+I, and F12 are all currently no-ops in Claude Desktop. With DevTools available I could have surgically inspected the renderer state in five minutes; without it, this turned into multi-hour filesystem archaeology. Even a hidden flag to enable DevTools in extensions-debugging mode would help.
- Show the drop source in the consent dialog. Currently the user sees only
Attach 'index.js' to this session?— they cannot tell that the request came from an extension's startup behavior rather than a paste or drag they performed themselves. Showing the source path (or at least the source category — "an extension" vs. "an OS drag from Explorer") would have shortened diagnosis from hours to seconds.
Diagnostic discoverability
The path I had to take to find this:
- The dialog said "index.js" — generic and unhelpful
- I assumed the prior session's diagnosis (stuck IndexedDB draft) was correct, wrote a
classic-level-based deletion script, ran into theidb_cmp1comparator mismatch (Chromium IDB's custom comparator is not supported by vanilla leveldb bindings) - Nuclear-renamed the entire
https_claude.ai_0.indexeddb.leveldbdirectory — symptom persisted - Grepped Local Storage and Session Storage leveldbs — no matches
- Grepped UTF-16LE encodings — no matches
- Finally grepped
logs/main.logfor the file path and foundHandling file drop:— root cause obvious within seconds
A "View Logs" link in the consent dialog, or simply richer dialog text ("This file is being attached by the Kapture Browser Automation extension. [Block] [Allow] [Cancel]"), would have collapsed this entire journey.
Status
Workaround in place (kapture uninstalled). Upstream bug filed at williamkapke/kapture for the proximate cause. This issue is filed for the host-app hardening gap.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗