@ulpi/browse

Security

Domain allowlists, action policies, encrypted credential vault, and content boundaries.

Domain Allowlist

Restrict where the browser can navigate. Any navigation or resource load outside the allowlist is blocked.

browse --allowed-domains "example.com,*.api.io" goto https://example.com

Or set in browse.json:

{
  "allowedDomains": ["example.com", "*.api.io"]
}

Wildcards (*) match any subdomain. Without an allowlist, the browser can navigate anywhere.

Action Policy

Control which commands agents can run using a browse-policy.json file in your project root:

{
  "default": "allow",
  "deny": ["js", "eval"],
  "confirm": ["goto"],
  "allow": ["text", "snapshot", "click", "fill"]
}

Rules

  • deny — command is blocked, returns an error
  • confirm — command requires user confirmation before executing
  • allow — command runs without restriction
  • default — fallback for commands not in any list ("allow" or "deny")

Precedence: deny > confirm > allow whitelist > default.

Configuration

The policy file is auto-discovered by walking up from the current directory. Override the path with:

export BROWSE_POLICY=/path/to/my-policy.json

Or require confirmation for specific commands via environment variable:

export BROWSE_CONFIRM_ACTIONS=goto,js,eval

The policy file hot-reloads — changes take effect without restarting the server.

Content Boundaries

When reading content from untrusted pages, use content boundaries to prevent prompt injection attacks:

browse --content-boundaries text

Output is wrapped in nonce-delimited markers:

---BROWSE-CONTENT-abc123---
<page content here>
---/BROWSE-CONTENT-abc123---

The nonce changes per request, making it impossible for page content to inject fake boundaries.

Encrypted Credential Vault

Store login credentials encrypted at rest using AES-256-GCM:

# Set encryption key (do this once)
export BROWSE_ENCRYPTION_KEY=$(openssl rand -base64 32)

# Save credentials
browse auth save myapp https://app.com user@example.com mypassword

# Auto-login later
browse auth login myapp

Vault Operations

browse auth list                  # List saved credentials (names only, no passwords)
browse auth delete myapp          # Remove saved credentials

Credentials are stored in .browse/auth/ — encrypted files, never plaintext. The encryption key should be stored securely (environment variable, secrets manager).

Best Practices

  1. Always use --allowed-domains when browsing untrusted sites
  2. Always use --content-boundaries when feeding page content to an LLM
  3. Never hardcode credentials — use the encrypted vault or --password-stdin
  4. Use sessions for isolation — each agent gets its own cookies and state
  5. Use action policies to restrict dangerous commands (js, eval) in production environments

On this page