Install
$ agentstack add skill-ohvignas-claude-electron-skills-security ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Electron Security
Overview
Electron apps run web content with OS-level reach, so an XSS bug can become remote code execution. Security is defense-in-depth: keep the renderer untrusted (isolated + sandboxed), expose only narrow APIs over IPC, lock down navigation/new-windows/permissions, and flip build-time fuses.
When to use
- Configuring
webPreferencesfor anyBrowserWindow/``. - Loading any remote or partially-trusted content (XSS could "jump out of the renderer").
- Adding a Content-Security-Policy, IPC handlers,
shell.openExternal, or window/navigation handling. - Pre-release hardening:
@electron/fuses, asar integrity, permission handlers, packaging review.
When NOT to use: for the IPC mechanics themselves (invoke/handle/contextBridge) see process-model-ipc; for navigation/` deep-dives see webcontents-navigation`.
Quick reference
| API / option | Purpose | |---|---| | contextIsolation: true | Preload + Electron run in a separate context (default ≥12). | | nodeIntegration: false | No Node globals in the renderer (default). | | sandbox: true | Chromium OS sandbox for the renderer (default ≥20). | | webSecurity: true | Keep same-origin policy on (never disable). | | session.defaultSession.webRequest.onHeadersReceived | Inject a Content-Security-Policy header. | | contents.setWindowOpenHandler(handler) | Deny-by-default window.open/target=_blank. | | contents.on('will-navigate', …) | Block navigation off your origin. | | e.senderFrame / validateSender | Verify the origin of every IPC message. | | ses.setPermissionRequestHandler(handler) | Approve/deny camera, geolocation, etc. (default: approve all). | | flipFuses(electron, {…}) | Build-time fuses: RunAsNode, OnlyLoadAppFromAsar, … |
Example
// main.js — a hardened window, app-wide CSP, validated IPC, deny-by-default popups.
const { app, BrowserWindow, ipcMain, session, shell } = require('electron')
const path = require('node:path')
function createWindow () {
const win = new BrowserWindow({
webPreferences: {
contextIsolation: true, // isolate preload from page (default, but be explicit)
nodeIntegration: false, // no Node in the renderer
sandbox: true, // OS sandbox: an XSS can't reach the FS/Node
webSecurity: true, // keep same-origin policy
preload: path.join(app.getAppPath(), 'preload.js')
}
})
win.loadURL('https://example.com')
}
app.whenReady().then(() => {
// CSP as a response header is enforced even if the page omits its own meta tag.
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': ["default-src 'self'; script-src 'self'"]
}
})
})
// Only this trusted frame may invoke privileged IPC.
ipcMain.handle('get-secrets', (event) => {
if (new URL(event.senderFrame.url).host !== 'example.com') return null
return getSecrets()
})
createWindow()
})
// Apply to EVERY webContents (windows AND ), not just the first window.
app.on('web-contents-created', (_event, contents) => {
// Deny all new-window requests; route safe links to the OS browser instead.
contents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('https://example.com/')) setImmediate(() => shell.openExternal(url))
return { action: 'deny' }
})
// Block navigation away from our origin.
contents.on('will-navigate', (event, navigationUrl) => {
if (new URL(navigationUrl).origin !== 'https://example.com') event.preventDefault()
})
})
Common mistakes
- Disabling
webSecurity(or settingallowRunningInsecureContent) to "fix" CORS/mixed content — this turns off the same-origin policy. Fix the server/CSP instead. - Exposing raw
ipcRenderer.on/sendviacontextBridge— wrap each channel in a typed function so the page can't drive arbitrary IPC. - Returning
{ action: 'allow' }by default insetWindowOpenHandler, or handling onlyBrowserWindowand forgetting `— useweb-contents-created` to cover all frames. - Trusting IPC senders — any web frame can message the main process; check
event.senderFrame.urlbefore privileged work. shell.openExternal(userControlledUrl)— can run arbitrary commands; only pass validated/hardcoded URLs.
Reference
Full API tables: [reference.md](reference.md)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ohvignas
- Source: ohvignas/claude-electron-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.