Skip to main content
The Palyra Browser Extension (Relay Companion) is a Manifest V3-compliant extension designed to bridge the gap between a user’s local browser and the Palyra ecosystem. It facilitates secure data extraction (snapshots, selections) and remote control (tab management) by relaying actions to the palyrad daemon or a dedicated palyra-browserd instance.

Overview and Purpose

The extension acts as a “Relay” that allows the Palyra agent to interact with the user’s active browsing session without requiring the agent to have direct OS-level control over the browser process. It provides capabilities for:
  • Context Capture: Extracting DOM snapshots and visible text from the active tab.
  • Remote Navigation: Opening and activating tabs within the user’s browser.
  • Security Isolation: Operating strictly over loopback interfaces with non-persistent tokens to minimize the attack surface.

Architecture and Data Flow

The extension follows the standard Manifest V3 architecture, utilizing a Background Service Worker for relay logic and Content Scripts for DOM interaction.

System Component Diagram

The following diagram illustrates the relationship between the extension components and the Palyra daemon. Relay Companion Entity Mapping Sources: apps/browser-extension/manifest.json#1-40, apps/browser-extension/background.js#159-187, apps/browser-extension/content_script.js#184-208

Data Flow: Page Snapshot Capture

When a snapshot is requested, the Background script injects a content script to perform capped extraction to ensure the payload does not exceed configured limits.
  1. Trigger: User or Agent initiates a snapshot via captureCurrentTabContext apps/browser-extension/background.js#117-142.
  2. Injection: background.js calls chrome.scripting.executeScript to ensure content_script.js is present apps/browser-extension/background.js#120-123.
  3. Extraction: content_script.js listens for palyra.collect_snapshot apps/browser-extension/content_script.js#184-187.
  4. Capping: collectDomSnapshotCapped and collectVisibleTextCapped traverse the DOM, appending to a buffer until maxBytes is reached apps/browser-extension/content_script.js#98-182.
  5. Relay: background.js receives the response and dispatches it via dispatchRelayAction to the loopback API apps/browser-extension/background.js#159-187.

Key Implementation Details

Security Posture

The extension implements several strict security guardrails:
  • Loopback Only: The relayBaseUrl is strictly validated to ensure it only targets 127.0.0.1, localhost, or ::1 apps/browser-extension/lib.mjs#81-83.
  • URL Allowlisting: Remote open_tab requests are checked against a prefix allowlist (e.g., https://) to prevent protocol handler abuse or navigation to sensitive local files apps/browser-extension/lib.mjs#126-192.
  • Token Handling: While relayToken and sessionId are stored in chrome.storage.local for convenience, the architecture is designed for “Pairing” flows where tokens can be rotated apps/browser-extension/background.js#40-57.
  • Credential Validation: normalizeRelayToken and normalizeSessionId enforce byte limits to prevent buffer overflow or DOS attempts against the relay endpoint apps/browser-extension/lib.mjs#104-124.

Content Script Logic

The content_script.js is optimized for performance and safety, avoiding heavy operations like outerHTML or innerText which can trigger expensive reflows or layout calculations.
FunctionPurposeLogic
collectDomSnapshotCappedSafe DOM extractionUses a stack-based traversal (non-recursive) to build a string representation of the DOM up to maxBytes apps/browser-extension/content_script.js#98-151.
collectVisibleTextCappedText extractionUses document.createTreeWalker with NodeFilter.SHOW_TEXT to gather visible strings apps/browser-extension/content_script.js#159-182.
clampUtf8BytesByte-level truncationEnsures strings are truncated without splitting multi-byte UTF-8 characters apps/browser-extension/lib.mjs#28-50.
Sources: apps/browser-extension/content_script.js#1-209, apps/browser-extension/lib.mjs#28-50

Pairing and Configuration

The extension requires pairing with a running Palyra daemon. This is managed via the popup.html interface and popup.js.

Configuration Schema

The extension persists the following configuration in chrome.storage.local under the key palyraRelayConfig:
KeyDefaultDescription
relayBaseUrlhttp://127.0.0.1:7142The loopback address of the Palyra daemon apps/browser-extension/lib.mjs#1.
sessionId""The active session identifier for the relay apps/browser-extension/background.js#22.
relayToken""Bearer token for authenticating with the daemon apps/browser-extension/background.js#23.
openTabAllowlistRawhttps://, http://127.0.0.1...CSV/Newline separated list of allowed URL prefixes apps/browser-extension/lib.mjs#2-6.
Sources: apps/browser-extension/background.js#17-30, apps/browser-extension/lib.mjs#1-12

Relay Action Dispatch

Actions are dispatched via dispatchRelayAction, which targets the /console/v1/browser/relay/actions endpoint. Relay Protocol Sequence Sources: apps/browser-extension/background.js#159-187, crates/palyra-daemon/src/transport/http/handlers/console/browser.rs#5-32

Testing and Validation

The extension includes a suite of Node.js-based tests that simulate the browser environment using the vm module. Sources: apps/browser-extension/tests/content_script.test.mjs#1-211, apps/browser-extension/tests/lib.test.mjs#1-84