Skip to content

VNX-356: Electron app silently grants permissions or accepts invalid certificates

Reports Electron main-process code that answers a security prompt for the user: permission request/check handlers that always grant, certificate-error handlers that always accept, a certificate verifier that always returns 0, and the ignore-certificate-errors switch.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-356
Severity Low
SARIF level note
Kind sast
Languages JavaScript / TypeScript
CWE CWE-356
CAPEC CAPEC-66
ATT&CK T1190
CWSS vector CWSS:1.0/TI:L/AP:A/AL:A/IC:N/FC:LT/RP:N/RL:A/AV:I/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L
Tags missing-unsafe-warning electron permissions tls cwe-356
Source internal/sast/rules/vnx-356.rego

Overview

VNX-356 maps to CWE-356: Product UI does not Warn User of Unsafe Actions. In an Electron app, the main process decides whether the user is ever asked about a dangerous action. This rule reports JavaScript/TypeScript code that makes that decision for the user with an unconditional “yes”:

  1. session.setPermissionRequestHandler(...) whose handler calls its callback with true unconditionally (camera, microphone, geolocation, notifications and every other permission are granted with no prompt).
  2. setPermissionCheckHandler(...) whose handler returns true unconditionally.
  3. app.on('certificate-error', ...) / webContents.on('certificate-error', ...) whose handler calls its callback with true unconditionally.
  4. setCertificateVerifyProc(...) whose handler calls its callback with 0 (trusted) unconditionally.
  5. app.commandLine.appendSwitch('ignore-certificate-errors'), unless it sits in a development-only branch (!app.isPackaged, isDev, NODE_ENV === 'development') within the three lines above.

A handler whose body (followed up to eight lines) contains a condition, ternary, comparison, allowlist lookup or switch is a decision and is not reported, nor is a callback given false, nor are test files, comments and string literals. Web confirmation dialogs are not judged: whether an action deserves a prompt is a design question that no line of code answers.

Why This Matters

Browsers warn before a site gets the camera or before loading a page with a bad certificate. An Electron app that grants or accepts everything removes that warning, so a compromised or injected page in the app’s window gets device access, and a network attacker can intercept TLS without the user ever seeing an error.

What Gets Flagged

// FLAGGED
session.defaultSession.setPermissionRequestHandler((webContents, permission, callback) => {
  callback(true);
});

app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
  event.preventDefault();
  callback(true);
});

app.commandLine.appendSwitch('ignore-certificate-errors');
// NOT FLAGGED: grants only named permissions to the app's own origin
session.defaultSession.setPermissionRequestHandler((webContents, permission, callback) => {
  const origin = new URL(webContents.getURL()).origin;
  callback(origin === 'https://app.example.com' && ALLOWED.has(permission));
});

Remediation

  1. Grant only the permissions the app needs, and only to origins it trusts; deny everything else (callback(false)).
  2. Never accept a certificate error unconditionally. If an internal host must be trusted, pin its certificate fingerprint and check the URL.
  3. Remove ignore-certificate-errors from production builds.

References

Suppressing this rule

Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):

# nosec vnx-356
// nosec vnx-356

Or record an ignore rule: vulnetix ignore add --rule vnx-356 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-356.rego, cli/internal/sast/docs/vnx-356.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.