Secure IPC patterns, credential storage, and API key management for Electron apps
View on GitHubplugins/aai-stack-electron/skills/electron-security/SKILL.md
February 1, 2026
Select agents to install to:
npx add-skill https://github.com/the-answerai/alphaagent-team/blob/main/plugins/aai-stack-electron/skills/electron-security/SKILL.md -a claude-code --skill electron-securityInstallation paths:
.claude/skills/electron-security/# Electron Security Skill
Security is critical in Electron apps. This skill covers secure IPC, credential storage, and protecting sensitive data.
## Secure IPC with contextBridge
NEVER expose Node.js directly to the renderer. Use contextBridge:
### Preload Script
```typescript
// electron/preload.ts
import { contextBridge, ipcRenderer } from 'electron';
// Define allowed channels
const validSendChannels = [
'keychain:set',
'keychain:delete',
'cli:detect',
'app:quit',
];
const validReceiveChannels = [
'keychain:result',
'cli:status',
'update:available',
];
const validInvokeChannels = [
'keychain:get',
'keychain:set',
'keychain:delete',
'cli:detect-claude',
'app:get-version',
'app:get-paths',
];
contextBridge.exposeInMainWorld('electronAPI', {
// Invoke pattern (request-response)
invoke: (channel: string, ...args: unknown[]) => {
if (validInvokeChannels.includes(channel)) {
return ipcRenderer.invoke(channel, ...args);
}
throw new Error(`Invalid channel: ${channel}`);
},
// Send pattern (fire-and-forget)
send: (channel: string, ...args: unknown[]) => {
if (validSendChannels.includes(channel)) {
ipcRenderer.send(channel, ...args);
}
},
// Receive pattern (listen for events)
on: (channel: string, callback: (...args: unknown[]) => void) => {
if (validReceiveChannels.includes(channel)) {
const subscription = (_event: Electron.IpcRendererEvent, ...args: unknown[]) =>
callback(...args);
ipcRenderer.on(channel, subscription);
return () => ipcRenderer.removeListener(channel, subscription);
}
throw new Error(`Invalid channel: ${channel}`);
},
// One-time listener
once: (channel: string, callback: (...args: unknown[]) => void) => {
if (validReceiveChannels.includes(channel)) {
ipcRenderer.once(channel, (_event, ...args) => callback(...args));
}
},
});
```
### TypeScript Declarations
```typescript
// src/client/types/electron.d.ts
exp