Security and quality

Deny unused permissions

Install a permission handler that rejects camera, microphone, notification, and other web permissions the app does not use.

Chromium can ask the user for permissions: camera, microphone, geolocation, notifications, screen capture, USB devices, and more. In a browser, the user gets a prompt. In Electron, you decide what happens. And if you decide nothing, Electron approves every request by default.

Desktop Notes needs none of these. So we deny all of them.

Add this after app.whenReady() resolves:

const { session } = require('electron')

session.defaultSession.setPermissionRequestHandler(
  (_webContents, _permission, callback) => {
    callback(false)
  }
)

session.defaultSession.setPermissionCheckHandler(() => false)

There are two handlers because Chromium has two code paths.

setPermissionRequestHandler runs when a page asks for something, like Notification.requestPermission(). We call callback(false) and the request is refused. No prompt appears.

setPermissionCheckHandler runs when a page checks a permission without asking for it, for example through navigator.permissions.query(). Returning false reports “denied”.

Implementing only the first one leaves a gap. Some web APIs check first and only request if the check says “prompt”. Electron documents both handlers for this reason. Install both.

If you ever need one

Say a future version wants notifications. Don’t switch to callback(true). Check the exact permission name, the requesting origin, the embedding origin, and the frame details, and allow only that one combination. Everything else stays denied.

A prompt is not a security policy. The handler decides which requests are valid before Chromium shows or grants anything. A user of Desktop Notes should never see a permission dialog.

Test it

Open renderer DevTools and run:

Notification.requestPermission().then(console.log)

It should print denied, with no operating-system prompt. Try navigator.permissions.query({ name: 'geolocation' }) too and check that state is denied.

Other sessions

session.defaultSession is the session our main window uses. If you later create a window with a custom partition or session option, it gets its own session object, and this policy does not apply to it automatically. Install the same two handlers there, or you’ll have one locked-down window and one wide open.

Lesson completed