← foreveragents.dev

Encryption

If data leaves the user's device, it should be unreadable to everyone except the intended recipient. If it does not need to leave, it should not.

Principles

The URL fragment pattern

URL fragments (after #) are not sent by browsers in HTTP requests. This makes them useful for carrying sensitive content such as encrypted agent configurations. Always encrypt keys, secrets, and agent configurations, before storing in URL fragments.

https://app.example.com/#eyJlbmMiOiJ4c2Fsc2EyMC1wb2x5MTMwNSIs...
    

The server can serve static files while the client reads the fragment, decrypts, and renders locally.

Algorithm choice

Consider XSalsa20-Poly1305 (via TweetNaCl) for in-browser symmetric encryption:

const nonce = nacl.randomBytes(24);
    const encrypted = nacl.secretbox(message, nonce, key); // key: 32 bytes
    const payload = new Uint8Array([...nonce, ...encrypted]);
    

Why this is often preferred in this architecture:

Note: AES-GCM can also be secure when used correctly; nonce management and implementation discipline are critical.

Key derivation from passwords

When using a human-memorable password, derive 32 raw bytes with PBKDF2 and use them as the NaCl secretbox key:

const keyMaterial = await crypto.subtle.importKey(
      'raw',
      new TextEncoder().encode(password),
      'PBKDF2',
      false,
      ['deriveBits']
    );

    const bits = await crypto.subtle.deriveBits(
      { name: 'PBKDF2', salt, iterations: 150000, hash: 'SHA-256' },
      keyMaterial,
      256
    );

    const key = new Uint8Array(bits); // 32 bytes for nacl.secretbox
    

Use per-payload random salts and store salt with ciphertext metadata.

Encrypted local storage

localStorage and sessionStorage are readable by scripts on the same origin. Encrypt before storing:

localStorage.setItem('state', base64(encrypt(JSON.stringify(state), key)));
    

For agents

  1. Never store plaintext secrets at rest nor in browser storage
  2. Use authenticated encryption for all serialized agent state
  3. Keep keys out of query parameters and server logs
  4. Encrypt full agent configuration where practical: API keys, prompts, model/provider settings, tool config
  5. Handle decryption failures safely and recoverably
  6. Warn users that browser extensions can access window.location.hash

← All contexts