or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

app-lifecycle.mddevelopment.mdindex.mdipc.mdmenu-system.mdnetwork-protocols.mdplatform-features.mdsecurity.mdsystem-integration.mdwindow-management.md
tile.json

security.mddocs/

Security Features

Security features including safe storage, context isolation, sandboxing, and secure communication patterns.

Capabilities

Safe Storage

Secure credential storage using system keychain services.

/**
 * Allows access to simple encryption and decryption of strings for storage on the local machine
 */
interface SafeStorage {
  /** Returns whether encryption is available */
  isEncryptionAvailable(): boolean;
  
  /** Encrypts a string and returns an encrypted buffer */
  encryptString(plainText: string): Buffer;
  
  /** Decrypts an encrypted buffer and returns the original string */
  decryptString(encrypted: Buffer): string;
  
  /** Sets the item data in the secure storage */
  setPassword(service: string, account: string, password: string): void;
  
  /** Retrieves the password from secure storage */
  getPassword(service: string, account: string): string;
  
  /** Deletes the password from secure storage */
  deletePassword(service: string, account: string): boolean;
  
  /** Returns the item data from secure storage */
  findPassword(service: string): string;
}

declare const safeStorage: SafeStorage;

Usage Examples:

const { safeStorage } = require('electron');

// Check if encryption is available
if (safeStorage.isEncryptionAvailable()) {
  console.log('Safe storage is available');
  
  // Encrypt sensitive data
  const sensitiveData = 'user-secret-token';
  const encrypted = safeStorage.encryptString(sensitiveData);
  
  // Store encrypted data (you would save this to a file or database)
  fs.writeFileSync('encrypted-data.bin', encrypted);
  
  // Later, decrypt the data
  const encryptedData = fs.readFileSync('encrypted-data.bin');
  const decrypted = safeStorage.decryptString(encryptedData);
  console.log('Decrypted:', decrypted);
  
  // Store password in system keychain
  safeStorage.setPassword('myapp', 'user@example.com', 'secret-password');
  
  // Retrieve password
  const password = safeStorage.getPassword('myapp', 'user@example.com');
  console.log('Retrieved password:', password);
} else {
  console.log('Safe storage is not available');
}

Context Isolation & Sandboxing

Security through process isolation and controlled API access.

/**
 * WebFrame controls the renderer frame's execution context
 */
interface WebFrame extends EventEmitter {
  /** Inserts CSS into the current web page and returns a unique key for the inserted CSS */
  insertCSS(css: string, options?: InsertCSSOptions): Promise<string>;
  
  /** Removes the inserted CSS from the current web page */
  removeInsertedCSS(key: string): Promise<void>;
  
  /** Evaluates code in page */
  executeJavaScript(code: string, userGesture?: boolean): Promise<any>;
  
  /** Work like executeJavaScript but evaluates scripts in an isolated context */
  executeJavaScriptInIsolatedWorld(worldId: number, scripts: WebSource[], userGesture?: boolean): Promise<any>;
  
  /** Set the security origin, content security policy and name of the isolated world */
  setIsolatedWorldInfo(worldId: number, info: IsolatedWorldInfo): void;
  
  /** Resources will be loaded from this scheme regardless of the current page's Content Security Policy */
  registerURLSchemeAsSecure(scheme: string): void;
  
  /** Resources will be loaded from this scheme regardless of the current page's Content Security Policy */
  registerURLSchemeAsBypassingCSP(scheme: string): void;
  
  /** Registers the scheme as secure scheme */
  registerURLSchemeAsPrivileged(scheme: string, options?: RegisterURLSchemeAsPrivilegedOptions): void;
  
  /** Changes the zoom factor to the specified factor */
  setZoomFactor(factor: number): void;
  
  /** Returns the current zoom factor */
  getZoomFactor(): number;
  
  /** Changes the zoom level to the specified level */
  setZoomLevel(level: number): void;
  
  /** Returns the current zoom level */
  getZoomLevel(): number;
  
  /** Sets a provider for spell checking in input fields and text areas */
  setSpellCheckProvider(language: string, provider: SpellCheckProvider): void;
  
  /** The top frame in the frame hierarchy to which frame belongs */
  readonly top: WebFrame;
  
  /** The frame which opened frame, null if there's no opener or opener has been closed */
  readonly opener: WebFrame | null;
  
  /** The parent frame of frame, the property would be null if frame is the top frame in the frame hierarchy */
  readonly parent: WebFrame | null;
  
  /** The first child frame of frame, the property would be null if frame has no children */
  readonly firstChild: WebFrame | null;
  
  /** The next sibling frame of frame, the property would be null if frame is the last frame in the frame hierarchy */
  readonly nextSibling: WebFrame | null;
  
  /** A unique identifier for the frame */
  readonly frameId: number;
  
  /** The name of the frame */
  readonly name: string;
  
  /** The operating system pid of the process which owns this frame */
  readonly processId: number;
  
  /** The unique identifier for the frame's internal routing */
  readonly routingId: number;
  
  /** Whether the frame is out of process */
  readonly isOutOfProcess: boolean;
  
  /** The current URL of the frame */
  readonly url: string;
}

declare const webFrame: WebFrame;

Usage Examples:

// In renderer process with context isolation
const { webFrame } = require('electron');

// Execute code in isolated world
async function executeInIsolatedWorld() {
  const worldId = 1000;
  
  // Set up isolated world
  webFrame.setIsolatedWorldInfo(worldId, {
    securityOrigin: 'chrome-extension://my-extension-id',
    csp: "script-src 'self' 'unsafe-inline';",
    name: 'My Extension World'
  });
  
  // Execute code in isolated world
  const result = await webFrame.executeJavaScriptInIsolatedWorld(worldId, [
    {
      code: `
        // This code runs in isolation
        window.myExtensionAPI = {
          version: '1.0.0',
          getData: () => 'isolated data'
        };
        'Isolated world setup complete';
      `
    }
  ]);
  
  console.log('Isolated execution result:', result);
}

// Secure CSS injection
async function injectSecureCSS() {
  const css = `
    .secure-highlight {
      background-color: yellow;
      border: 2px solid red;
    }
  `;
  
  const key = await webFrame.insertCSS(css, {
    cssOrigin: 'user'
  });
  
  // Store key to remove later
  window.injectedCSSKey = key;
}

// Remove injected CSS
async function removeSecureCSS() {
  if (window.injectedCSSKey) {
    await webFrame.removeInsertedCSS(window.injectedCSSKey);
    delete window.injectedCSSKey;
  }
}

Secure preload script example:

// preload.js - Secure API exposure
const { contextBridge, ipcRenderer } = require('electron');

// Validate and sanitize input
function sanitizeInput(input) {
  if (typeof input !== 'string') {
    throw new Error('Input must be a string');
  }
  return input.replace(/[<>]/g, '');
}

// Expose secure API
contextBridge.exposeInMainWorld('secureAPI', {
  // Safe methods
  platform: process.platform,
  version: process.versions.electron,
  
  // Controlled file operations
  readFile: (path) => {
    // Validate path
    if (!path || typeof path !== 'string') {
      throw new Error('Invalid file path');
    }
    
    // Only allow certain directories
    const allowedDirs = ['/app/data/', '/app/config/'];
    const isAllowed = allowedDirs.some(dir => path.startsWith(dir));
    
    if (!isAllowed) {
      throw new Error('Access denied');
    }
    
    return ipcRenderer.invoke('secure-read-file', path);
  },
  
  // Safe IPC communication
  sendMessage: (channel, data) => {
    // Whitelist allowed channels
    const allowedChannels = ['user-action', 'settings-update', 'log-message'];
    
    if (!allowedChannels.includes(channel)) {
      throw new Error('Channel not allowed');
    }
    
    // Sanitize data
    const sanitizedData = sanitizeInput(JSON.stringify(data));
    
    return ipcRenderer.invoke('secure-message', channel, JSON.parse(sanitizedData));
  },
  
  // Remove all listeners on cleanup
  cleanup: () => {
    ipcRenderer.removeAllListeners();
  }
});

Content Security Policy

CSP implementation for web content security.

/**
 * Control the security policy of web content
 */
interface ContentSecurityPolicy {
  /** Sets the Content Security Policy header */
  setHeader(policy: string): void;
  
  /** Gets the current Content Security Policy */
  getHeader(): string | null;
  
  /** Reports CSP violations */
  reportViolation(violation: CSPViolation): void;
}

/**
 * WebSecurity manages security settings for web content
 */
interface WebSecurity {
  /** Disables web security warnings */
  disable(): void;
  
  /** Enables web security */
  enable(): void;
  
  /** Returns whether web security is enabled */
  isEnabled(): boolean;
}

Usage Examples:

// Set up Content Security Policy
const { BrowserWindow } = require('electron');

function createSecureWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      enableRemoteModule: false,
      sandbox: true,
      webSecurity: true,
      allowRunningInsecureContent: false,
      experimentalFeatures: false,
      preload: path.join(__dirname, 'secure-preload.js')
    }
  });
  
  // Set security headers
  win.webContents.session.webRequest.onHeadersReceived((details, callback) => {
    callback({
      responseHeaders: {
        ...details.responseHeaders,
        'Content-Security-Policy': [
          "default-src 'self'; " +
          "script-src 'self' 'unsafe-inline'; " +
          "style-src 'self' 'unsafe-inline'; " +
          "img-src 'self' data: https:; " +
          "connect-src 'self' https: wss:; " +
          "font-src 'self' data:; " +
          "object-src 'none'; " +
          "base-uri 'self'; " +
          "form-action 'self';"
        ],
        'X-Content-Type-Options': ['nosniff'],
        'X-Frame-Options': ['DENY'],
        'X-XSS-Protection': ['1; mode=block'],
        'Referrer-Policy': ['strict-origin-when-cross-origin']
      }
    });
  });
  
  return win;
}

// Handle CSP violations
function setupCSPViolationHandler(session) {
  session.webRequest.onBeforeRequest((details, callback) => {
    // Log potential security violations
    if (details.url.includes('evil-script.js')) {
      console.warn('Blocked potentially malicious script:', details.url);
      callback({ cancel: true });
      return;
    }
    
    callback({});
  });
}

Permissions Management

Control renderer process permissions and capabilities.

/**
 * Permission management for web content
 */
interface PermissionManager {
  /** Request permission for a specific capability */
  requestPermission(permission: string, origin: string): Promise<boolean>;
  
  /** Check if permission is granted */
  checkPermission(permission: string, origin: string): boolean;
  
  /** Revoke permission */
  revokePermission(permission: string, origin: string): void;
  
  /** List all granted permissions */
  getGrantedPermissions(origin: string): string[];
}

Usage Examples:

// Main process permission handling
const { session } = require('electron');

// Set up permission handlers
session.defaultSession.setPermissionRequestHandler((webContents, permission, callback, details) => {
  const { requestingUrl, isMainFrame } = details;
  
  // Define permission policies
  const permissionPolicies = {
    'notifications': {
      allowedOrigins: ['https://myapp.com', 'https://api.myapp.com'],
      requiresMainFrame: true
    },
    'camera': {
      allowedOrigins: ['https://myapp.com'],
      requiresUserGesture: true
    },
    'microphone': {
      allowedOrigins: ['https://myapp.com'],
      requiresUserGesture: true
    },
    'geolocation': {
      allowedOrigins: [],
      requiresUserGesture: true
    }
  };
  
  const policy = permissionPolicies[permission];
  
  if (!policy) {
    console.log(`Permission denied: ${permission} (no policy)`);
    callback(false);
    return;
  }
  
  // Check origin
  const origin = new URL(requestingUrl).origin;
  if (!policy.allowedOrigins.includes(origin)) {
    console.log(`Permission denied: ${permission} (origin not allowed)`);
    callback(false);
    return;
  }
  
  // Check if main frame is required
  if (policy.requiresMainFrame && !isMainFrame) {
    console.log(`Permission denied: ${permission} (not main frame)`);
    callback(false);
    return;
  }
  
  console.log(`Permission granted: ${permission} for ${origin}`);
  callback(true);
});

// Set up permission check handler
session.defaultSession.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
  // Always allow for our app's origin
  if (requestingOrigin === 'https://myapp.com') {
    return true;
  }
  
  // Block everything else
  return false;
});

Types

interface WebSource {
  code: string;
  url?: string;
  startLine?: number;
}

interface IsolatedWorldInfo {
  securityOrigin?: string;
  csp?: string;
  name: string;
}

interface RegisterURLSchemeAsPrivilegedOptions {
  secure?: boolean;
  bypassCSP?: boolean;
  allowServiceWorkers?: boolean;
  supportsFetchAPI?: boolean;
  corsEnabled?: boolean;
  stream?: boolean;
}

interface SpellCheckProvider {
  spellCheck: (words: string[], callback: (misspeltWords: string[]) => void) => void;
}

interface CSPViolation {
  directive: string;
  effectiveDirective: string;
  originalPolicy: string;
  sourceFile: string;
  sample: string;
  disposition: 'enforce' | 'report';
  statusCode: number;
  lineNumber: number;
  columnNumber: number;
}