fix(vscode,pi): correct OSCrypt safeStorage encryption and allow custom deployment IDs for Pi - #14
Closed
shzdehmd wants to merge 2 commits into
Closed
Conversation
…rage Linux: swap v10/v11 prefixes (v11=keyring, v10=basic_text) and use 1 PBKDF2 iteration instead of 1003 (macOS-only). The old params produced ciphertext VS Code's safeStorage couldn't decrypt, causing it to silently delete the secret and lose the API key on every restart. Windows: replace raw-DPAPI-on-plaintext with v10 + AES-256-GCM using a DPAPI-protected 32-byte key loaded from VS Code's Local State file (os_crypt.encrypted_key). Fix the DPAPI round-trip to use buffer-based functions that preserve binary data (the old UTF-8 string path corrupted the 32-byte key into 45 bytes). macOS: unchanged (v10 + AES-128-CBC + 1003 iterations + keychain master password) — matches Chromium's OSCrypt macOS scheme. Verified against Chromium os_crypt/async/common/algorithm.mojom and encryptor.cc, and confirmed the Windows blob layout (v10 + nonce(12) + ct + tag(16) at end) via a ground-truth probe against Electron safeStorage on Windows.
…ts/<id>)
piModelsToRegister gated custom model registration on
startsWith('accounts/fireworks/'), excluding custom deployment IDs
(accounts/<user>/deployments/<id>). Broadened to startsWith('accounts/')
so custom deployments flow through buildPiCustomFireworksModelEntry with
graceful defaults (128K context, no cost block) — same as any other
unrecognized accounts/ ID. Other harnesses (Claude, VS Code, Codex,
OpenCode) already accept these IDs freely; Pi was the only one with the
prefix filter.
Collaborator
|
thank you! fixed in v0.9.0 |
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.
Summary
Two bug fixes in this PR:
1. VS Code safeStorage encryption (Linux + Windows)
The VS Code harness writes the Fireworks API key as an Electron
safeStorage-encrypted blob intostate.vscdb. The OSCrypt parameters were wrong on Linux and Windows, so VS Code'ssafeStorage.decryptStringcould not decrypt the ciphertext — it silently deleted the secret and the API key was lost on every restart.Linux: The
v10/v11version prefixes were swapped between the keyring and basic_text branches, and the PBKDF2 iteration count was 1003 (macOS-only) instead of 1. Chromium'sos_crypt/async/common/algorithm.mojomconfirmskAES128CBCis the "v11 os_crypt_sync encryption on Linux" with 1 iteration.Windows: The code used raw DPAPI on the whole plaintext (no prefix), but modern Chromium uses
v10+ AES-256-GCM with a DPAPI-protected 32-byte key stored in VS Code'sLocal Statefile (os_crypt.encrypted_key). Additionally, the DPAPI round-trip corrupted the 32-byte key becausewindowsUnprotectconverted raw bytes through a UTF-8 string (45 bytes instead of 32).macOS: Unaffected —
v10+ AES-128-CBC + 1003 iterations + keychain master password was already correct.Changes (
vscode-safestorage.mjs):v11+ keyring password (was v10),v10+ "peanuts" basic_text (was v11)v10+ AES-256-GCM (v10(3) + nonce(12) + ciphertext + tag(16), tag at end)loadWindowsOsCryptKeyto read the DPAPI-protected 32-byte key fromLocal State(os_crypt.encrypted_key→ strip 5-byteDPAPIprefix → DPAPI-unprotect)windowsProtectBuffer/windowsUnprotectBufferthat preserve binary data (no UTF-8 conversion)Local Statekey prefix is notDPAPIlocalStatePaththroughencryptSecret/decryptSecret/isSecretEncryptionAvailableand all call sites invscode-core.mjsandvscode-firerouter-core.mjsVerification: Ground-truth probe on Windows (Electron 42) confirmed:
encryptSecretoutput decrypts correctly with Electron's realsafeStorage.decryptStringsafeStorage.encryptStringoutput decrypts correctly with fireconnect'sdecryptSecretfireconnect vscode oninto the realstate.vscdbdecrypts correctly with VS Code's ownLocal Statekeyfireconnect vscode statusreads the key back (Key present: yes)Parameters confirmed against Chromium's
os_crypt/async/common/algorithm.mojomandencryptor.cc.2. Pi custom deployment model IDs
Custom deployment IDs (
accounts/<user>/deployments/<id>) worked with all harnesses except Pi.piModelsToRegistergated custom model registration onstartsWith("accounts/fireworks/"), excluding user-specific deployment paths. Every other harness (Claude, VS Code, Codex, OpenCode) accepts anyaccounts/...ID freely.Fix: Broadened the guard to
startsWith("accounts/")inpi-fireworks-models.mjs:216. Custom deployments now flow throughbuildPiCustomFireworksModelEntrywith graceful defaults (128K context, no cost block) — same degradation any unrecognizedaccounts/fireworks/...router gets.Test plan
vscode-safestorage.test.mjs: Linux prefix/iteration matrix (proves 1-iter vs 1003-iter are incompatible), Windows AES-256-GCM round-trip/layout/nonce-randomness/tamper-detection,Local Stateerror paths (missing file, missing field, wrong prefix, bad JSON)pi-fireworks-models.test.mjs: custom deployment ID registration and effective model resolutiondev-cloudpos:fireconnect vscode on --api-key→ blob instate.vscdbdecrypts with VS Code'sLocal Statekey →fireconnect vscode statusreads it backfireconnect pi on --main accounts/ahmadshahzad/deployments/ub9lvh50works as expected