Sandbox & Security

Widgets run in a controlled environment that prevents interference with other widgets and protects the host overlay.

Network Isolation

Widgets cannot make direct fetch or XMLHttpRequest calls. All HTTP traffic goes through the backend proxy:
// This is the only way to make HTTP requests
const res = await SBCanvas.http('https://api.example.com/data', {
  method: 'GET'
});
The proxy applies rate limiting and domain restrictions configured per overlay.

Timer Management

Raw setTimeout and setInterval are available but not tracked. Use SBCanvas.setTimeout and SBCanvas.setInterval instead — they’re automatically cancelled when the widget unloads:
// Good: cleaned up automatically
SBCanvas.setTimeout(() => hideAlert(), 5000);

// Risky: can fire after widget is gone
setTimeout(() => hideAlert(), 5000);

Storage Isolation

SBCanvas.store is namespaced per widget. One widget cannot read or write another widget’s store data:
// Widget A
await SBCanvas.store.set('score', 100);

// Widget B — this is a different 'score' key
await SBCanvas.store.set('score', 50);

Cross-Widget Communication

Widgets communicate through named channels only:
const ch = SBCanvas.channel('score');
ch.publish({ points: 42 });
ch.subscribe((data) => console.log(data.points));
There’s no way to access another widget’s DOM, variables, or internal state directly.

Input Sanitization

Always sanitize user-generated content before rendering:
// Safe: escapes HTML entities
el.textContent = activity.username;

// Safe: explicit sanitization for HTML context
el.innerHTML = `<span>${SBCanvas.sanitize.html(activity.message)}</span>`;

// Dangerous: never do this
el.innerHTML = activity.message;
Available sanitizers:
MethodUse For
sanitize.html(str)Escaping HTML entities
sanitize.js(str)Escaping for JS string context
sanitize.url(str)Escaping URLs
sanitize.attr(str)Escaping HTML attribute values

Best Practices

  • Use SBCanvas.http for all network requests
  • Use SBCanvas.setTimeout/setInterval for automatic cleanup
  • Use textContent for user-generated text (never raw innerHTML)
  • Use SBCanvas.store for persistence (not localStorage directly)
  • Keep event handlers fast — the overlay runs at 60fps
  • Clean up DOM elements you create dynamically