1. Application
  2. Security Best Practices

Application

Security Best Practices

Guidelines for building secure desktop applications with ToDesktop.

Overview

ToDesktop provides a sandboxed API layer — your app doesn't have direct access to Node.js or raw Electron APIs. This significantly reduces the attack surface compared to traditional Electron apps. However, following security best practices remains important to protect your users.

Keep Your App Updated

Release your app regularly to ensure you're running the latest versions of:

  • Electron — receives security patches for Chromium and Node.js vulnerabilities
  • Chromium — the browser engine that renders your app
  • ToDesktop Runtime — includes security improvements and bug fixes

Outdated dependencies are one of the most common sources of security vulnerabilities. Even if your code hasn't changed, rebuilding and releasing your app ensures users get the latest security fixes.

URL Handling

Only Load Trusted URLs

Your app should only load URLs from domains you control or explicitly trust. Untrusted URLs loaded in your app could potentially abuse ToDesktop APIs or mislead your users.

Configure Internal URLs Carefully

When defining internal URLs, be careful with regex patterns. Overly permissive patterns can unintentionally allow untrusted domains.

        // ❌ Too permissive - matches any URL containing "myapp"
.*myapp.*

// ✅ More specific - only matches your domain
^(https?:\/\/)?(.*\.)?myapp\.com\/.*

      

Window Opening Rules

The same caution applies to window opening rules. Ensure your regex patterns only match the specific URLs you intend to allow.

External Trigger Risk

App protocols (e.g., myapp://) can be triggered by any website or application on the user's system. A malicious website could craft a link like:

        <a href="myapp://malicious/path?data=attack">Click here</a>

      

Always Validate Protocol URLs

Never trust data from open-protocol-url events without validation:

        window.todesktop.on('open-protocol-url', (_, event) => {
  const url = new URL(event.url);

  // ✅ Validate the path matches expected patterns
  const allowedPaths = ['/login', '/open', '/share'];
  if (!allowedPaths.some(path => url.pathname.startsWith(path))) {
    event.preventDefault();
    return;
  }

  // ✅ Sanitize any parameters before using them
  const safeParam = encodeURIComponent(url.searchParams.get('id') || '');

  // Now safe to use...
});

      

Authentication

Validate Tokens from URLs

When implementing OAuth flows, tokens are passed via URL parameters. Always validate tokens before using them for authentication — don't assume they're legitimate just because they arrived via your redirect URL.

Avoid Logging Sensitive Data

Be mindful that tokens in URLs can appear in:

  • Application logs
  • Error tracking services
  • Browser history

Avoid logging full URLs that contain sensitive parameters.

Data Handling

Validate Data Used in URL Construction

When building URLs from stored data, validate the data matches expected patterns:

        const subdomain = localStorage.getItem('subdomain');

// ✅ Validate before using in URL
if (subdomain && /^[a-z0-9-]+$/i.test(subdomain)) {
  window.location = `https://${subdomain}.yourapp.com`;
}

      

Without validation, an attacker who can influence stored data could redirect users to malicious sites.

Use Encrypted Storage for Sensitive Data

For sensitive data like credentials or tokens, use the safeStorage API instead of plain localStorage:

        import { safeStorage } from '@todesktop/client-core';

if (await safeStorage.isEncryptionAvailable()) {
  // ✅ Encrypted at rest using OS-level encryption
  const encrypted = await safeStorage.encryptString(sensitiveData);
  localStorage.setItem('secureData', encrypted);
}

      

Plugins

File System Plugin

The File System plugin is restricted to whitelisted directories (documents, downloads, temp, etc.) and requires you to explicitly enable each function. Only enable the functions your app actually needs.

File Exec Plugin

The File Exec plugin executes bundled binaries. Only bundle executables from sources you trust, and be aware that these run with the same permissions as your desktop app.

Content Security Policy

Content Security Policy (CSP) headers are still valuable in desktop apps. They help prevent XSS attacks by restricting which scripts can execute and which resources can be loaded. Configure CSP on your web server to add defence in depth.

Summary

Area Key Practice
Updates Release regularly for latest Electron/Chromium security fixes
URLs Only load URLs from trusted domains
Internal URLs Use specific regex patterns, not overly permissive ones
Protocol handlers Always validate and sanitize incoming URLs
Authentication Validate tokens, avoid logging sensitive data
Data storage Use safeStorage for sensitive data, validate before URL construction
Plugins Enable only what you need, trust your bundled executables
CSP Configure Content Security Policy headers