How API Keys Are Secured and Stored in the SecureStorageService Extension
The SecureStorageService wraps VS Code's SecretStorage API to encrypt and store API keys at the OS level, ensuring credentials never appear in plain-text configuration files and remain accessible only through validated get, set, and remove operations.
The hbmartin/secure-design extension handles sensitive provider credentials using a dedicated SecureStorageService that abstracts away direct secret management. This service implements the StorageAdapter interface required by the AI SDK, ensuring that API keys are secured and stored within the extension's architecture using platform-native encryption rather than vulnerable configuration files.
Architecture of the SecureStorageService
Implementing the StorageAdapter Interface
The service fulfills the StorageAdapter contract in src/services/secureStorageService.ts, requiring a constructor that receives a vscode.SecretStorage instance injected by the extension host. This dependency injection pattern isolates secret handling from business logic, allowing the underlying storage mechanism to be swapped without modifying consumer code.
OS-Level Encryption via VS Code SecretStorage
Rather than implementing custom encryption, the service delegates to VS Code's native SecretStorage API. When storing values, VS Code encrypts data using the OS credential manager—Keychain on macOS, Credential Locker on Windows, and secret-service on Linux—ensuring API keys remain encrypted at rest and accessible only to the extension process.
How API Keys Are Secured and Stored
Storing Keys with the Set Method
The set method serializes key-value pairs to JSON before encryption. When CustomAgentService persists a provider token, it calls secureStore.set('openaiApiKey', { token: 'sk-...' }), which invokes secrets.store(key, json). VS Code encrypts the JSON payload before writing it to the user's secret store, preventing the raw token from appearing in logs or configuration files.
// Obtain the VS Code secret storage from the extension context
const secretStorage = context.secrets;
// Create the wrapper service
const secureStore = new SecureStorageService(secretStorage);
// Store the OpenAI key
await secureStore.set('openaiApiKey', { token: 'sk-...' });
Retrieving and Validating Credentials
Retrieval follows the reverse path through the get method. The service fetches the raw JSON string via secrets.get(key), then parses it back into an object. To prevent type corruption, the implementation validates the structure using assertRecordStringString, guaranteeing the result conforms to {[string]: string}. Parsing errors are caught and logged silently, ensuring malformed data never propagates to calling services.
const stored = await secureStore.get('openaiApiKey');
if (stored) {
const token = stored.token; // use the token with the OpenAI client
}
Removing Sensitive Data
When users revoke credentials or uninstall the extension, the remove method forwards deletion requests to secrets.delete(key). This immediately purges the encrypted entry from the OS credential manager, leaving no residual key material on the filesystem.
await secureStore.remove('openaiApiKey');
Integration with Extension Services
The CustomAgentService in src/services/customAgentService.ts consumes SecureStorageService to persist provider API keys under dedicated identifiers like "openaiApiKey", "anthropicApiKey", or "openrouterApiKey". By depending on the StorageAdapter interface rather than concrete implementation details, the agent service remains agnostic to whether credentials are stored in VS Code's secret storage, a remote vault, or a future alternative backend.
Summary
- The
SecureStorageServicewraps VS Code'sSecretStorageto provide OS-level encryption for API keys without custom cryptography. - Credentials are stored as encrypted JSON via the
setmethod, retrieved and validated viaget, and purged viaremove. - The implementation in
src/services/secureStorageService.tsenforces type safety throughassertRecordStringStringvalidation. - By implementing the
StorageAdapterinterface, the service decouples secret management from business logic inCustomAgentService.
Frequently Asked Questions
Where are API keys physically stored when using SecureStorageService?
API keys are encrypted by VS Code's SecretStorage and stored in the operating system's native credential manager—Keychain on macOS, Credential Locker on Windows, or the secret-service daemon on Linux—never in the extension's configuration files or workspace storage.
What happens if the stored JSON data becomes corrupted?
The get method in src/services/secureStorageService.ts wraps JSON parsing in a try-catch block. If parsing fails or the assertRecordStringString validation rejects the structure, the method logs the error and returns undefined, preventing malformed data from reaching the AI SDK or agent service.
Can I migrate existing API keys from settings.json to SecureStorageService?
Yes. The CustomAgentService can read legacy plain-text values from settings.json and migrate them by calling secureStorageService.set() with the appropriate provider key, then prompt the user to remove the sensitive value from their configuration file to complete the migration to encrypted storage.
Is the SecureStorageService dependent on VS Code specific APIs?
Yes. The service directly depends on vscode.SecretStorage injected through the constructor in src/services/secureStorageService.ts. While this ties the implementation to the VS Code extension host, the StorageAdapter interface abstraction allows future ports to other environments by implementing the same contract with a different storage backend.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →