Skip to content

feat: Add Windows support for import-desktop command#47

Merged
AmethystLiang merged 5 commits intostablyai:mainfrom
tusharmagar:feat/windows-desktop-import
Mar 6, 2026
Merged

feat: Add Windows support for import-desktop command#47
AmethystLiang merged 5 commits intostablyai:mainfrom
tusharmagar:feat/windows-desktop-import

Conversation

@tusharmagar
Copy link
Contributor

@tusharmagar tusharmagar commented Mar 5, 2026

Summary

  • Adds Windows support for agent-slack auth import-desktop, which was previously limited to macOS and Linux
  • Supports both the regular Electron installer (%APPDATA%\Slack) and Microsoft Store version (%LOCALAPPDATA%\Packages\com.tinyspeck.slackdesktop_*)
  • Implements DPAPI + AES-256-GCM cookie decryption (Windows uses a different encryption scheme than macOS/Linux)
  • Copies the Cookies SQLite DB to a temp file before reading, since Windows holds an exclusive file lock while Slack is running
  • URL-decodes the decrypted cookie value (Windows stores it URL-encoded)
  • Removes the win32 platform guard from refreshFromDesktopIfPossible()

How it works

On Windows, Chromium-based apps (including Slack/Electron) encrypt cookies using:

  1. An AES-256 key stored in Local Stateos_crypt.encrypted_key (base64, "DPAPI" prefixed)
  2. The AES key is decrypted via Windows DPAPI (ProtectedData.Unprotect) through PowerShell
  3. Cookies are then decrypted with AES-256-GCM (12-byte nonce + ciphertext + 16-byte tag)

This is different from macOS (Keychain + AES-128-CBC) and Linux (secret-tool/peanuts + AES-128-CBC).

Test plan

  • Tested on Windows 11 ARM64 (Parallels) with Slack installed from Microsoft Store
  • agent-slack auth import-desktop successfully extracts xoxc token + xoxd cookie
  • agent-slack auth test returns ok: true
  • agent-slack message send works with the imported credentials
  • Should also work with the regular (non-Store) Slack Windows installer (same data layout at %APPDATA%\Slack)

Note

Slack must be fully quit before running import-desktop on Windows, as it holds an exclusive lock on the Cookies database file. This is consistent with the macOS behavior where Slack's LevelDB is also locked while running.

Add support for extracting Slack credentials from the Windows desktop
app (both regular installer and Microsoft Store version).

- Add Windows Slack data paths (%APPDATA%\Slack and Microsoft Store package)
- Implement DPAPI + AES-256-GCM cookie decryption via PowerShell
- Copy Cookies DB to temp file before reading (Windows file locking)
- URL-decode the decrypted cookie value
- Allow refreshFromDesktopIfPossible on win32
@AmethystLiang
Copy link
Contributor

Here are the feedback from Codex

• 1. High: require(...) inside an ESM module will break in Node runtime on the Windows path.
In desktop.ts line 407:407, decryptCookieWindows does:
const { createDecipheriv: createDecipherivGcm } = require("node:crypto")...
This repo is ESM ("type": "module"), so require is not defined in standard Node ESM execution. If import-
desktop is used on Windows in Node builds, this can throw ReferenceError: require is not defined.
2. Medium: PowerShell command construction is unsafe/fragile for valid Windows paths containing '.
In desktop.ts lines 429-433:429, temp file paths are injected into single-quoted PowerShell strings without
escaping.
A profile path like C:\Users\O'Connor... will break the script (and can become command-injection-prone in
principle). This can cause Windows auth import to fail for legitimate user profiles.
3. Low: Feature/docs mismatch for platform support.
PR adds Windows desktop import support, but README still frames auto-auth as macOS-only (see README.md line
98:98: “On macOS, authentication happens automatically”). This is now outdated and likely to confuse users.

 Once it's addressed, we can merge this in

tusharmagar and others added 3 commits March 6, 2026 10:49
- Remove require("node:crypto") in ESM module; use existing top-level
  createDecipheriv import instead (fixes ReferenceError in Node ESM)
- Escape single quotes in PowerShell temp file paths to prevent breakage
  and command injection for profiles like C:\Users\O'Connor
- Update README auth section to reflect Windows platform support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace execSync with execFileSync for PowerShell invocation to bypass
  cmd.exe shell interpolation, consistent with every other exec call in
  the file. Eliminates double-quote injection surface.
- Add existence check for decrypted key file after PowerShell DPAPI call
  to provide a meaningful error instead of cryptic ENOENT.
- Update JSDoc to document v10/v11 prefix support (both are handled).
- Remove unused execSync import.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Clarify that authentication is automatic on both macOS and Windows.
- Update command documentation to reflect Windows support for `import-desktop` command.
@tusharmagar
Copy link
Contributor Author

Hey @AmethystLiang, I have addressed the above comments, and the PR should be ready to merge. Please check it out.

The repo was added as a git submodule inside itself, which is
clearly unintentional. Remove the empty submodule entry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@AmethystLiang AmethystLiang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All 3 Codex feedback items verified as addressed:

  1. require() in ESM — Fixed: createDecipheriv now uses the top-level ESM import from node:crypto
  2. PowerShell injection — Fixed: single quotes escaped via replaceAll("'", "''") before interpolation
  3. Docs mismatch — Fixed: README, SKILL.md, and commands.md updated for Windows support

Code looks good — LGTM!

@AmethystLiang AmethystLiang merged commit e097620 into stablyai:main Mar 6, 2026
AmethystLiang added a commit that referenced this pull request Mar 7, 2026
feat: Add Windows support for import-desktop command
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.

2 participants