Skip to main content
AI agents need access to tools and data to be useful, but that same access creates risk. This page explains why Char’s security architecture takes the form it does—the threats it addresses, the constraints it imposes, and the tradeoffs it accepts.

The Threat Model

Most browser automation tools give AI agents ambient access to the user’s browsing context—cookies, sessions, DOM content, network requests. This creates what security researcher Simon Willison calls the “lethal trifecta”: When all three conditions exist, an attacker can embed malicious instructions in content the agent reads (a web page, an email, a document), causing it to leak private data or perform unauthorized actions. The attack surface isn’t a bug—it’s inherent to the architecture. Char addresses this threat model by removing these conditions structurally rather than trying to filter them behaviorally.

The Design Principles

Char’s security architecture follows three principles:

1. No Credential Storage

Char doesn’t store user passwords, session tokens, or shared secrets. Authentication is delegated entirely to your identity provider (Okta, Azure AD, Auth0, Google, etc.). When a user interacts with the agent, your application passes their existing JWT token. Char validates the token signature against your IDP’s public keys, extracts the user identity, and discards the token. There’s no token database to breach. This has implications:
  • Centralized revocation. Disable a user in your IDP and their Char access ends immediately. No separate system to update.
  • No shared secrets. Char validates signatures using public key cryptography. We never see your IDP’s client secret.
  • Inherited security. Your IDP’s MFA, password policies, and brute-force protection apply automatically. Char doesn’t implement these—it trusts your IDP already does.
The tradeoff is dependency. If your IDP is unavailable, users can’t authenticate to Char.
See Federated Authentication for why this is different from SSO and how token validation works in detail.

2. Infrastructure-Level Isolation

Every user gets their own isolated execution context—not through application-level access control (WHERE user_id = ?), but through infrastructure-level isolation using Cloudflare Durable Objects. The distinction matters. Application-level isolation relies on every query having the correct filter. If a developer forgets a WHERE clause or writes a bug, data can leak. Infrastructure-level isolation means there’s literally no code path that could return another user’s data—each user’s state exists in a separate execution context. Each Durable Object maintains:
  • The user’s active tool connections (which browser tabs are connected)
  • Their tool registry (what tools are currently available)
  • Their conversation threads (message history)
Cross-user access isn’t prevented by policy—it’s prevented by there being no shared state to access.
See Tool Hub for why Durable Objects were chosen over alternatives like Redis or traditional databases.

3. Explicit Context Only

The agent sees only what is explicitly provided through defined interfaces:
Context SourceWhat the Agent Sees
ConversationMessages typed by the user
SkillsSKILL.md files your developers registered
Tool schemasNames and input schemas—not implementations
Tool outputsResults returned when tools execute
The agent does not see:
  • The page’s DOM
  • Cookies or localStorage
  • Other users’ data
  • Ambient browser state
  • Anything not explicitly passed through a tool
This explicitness breaks the prompt injection attack chain. If a malicious page contains hidden instructions, the agent never sees them—unless a tool explicitly extracts and returns that content. And if a tool does return it, the content passes through defined boundaries that can be logged and audited.
See Context Isolation for how this compares to browser automation approaches and why it prevents prompt injection.

The Trust Model

Not all tools are equally trusted. Char distinguishes between internal and external tools based on who controls them. Internal tools are part of your enterprise—MCP servers you operate, browser-based tools in your applications. The reasoning: if an internal tool misbehaves, that’s either a bug in your code or a compromised internal system. Both are your enterprise’s responsibility to address. Char treating your internal tools as hostile would be like your database distrusting your own API. External tools come from third parties—SaaS applications, public APIs, vendor MCP servers. Your enterprise doesn’t control this code, so Char applies more scrutiny. External tool responses pass through validation before reaching the agent. The boundary is defined by your identity infrastructure. Tools that authenticate via your IDP are internal. Everything else is external.
See Trust Boundaries for how this trust model is enforced and why internal tools aren’t validated the same way.

How Requests Flow

Every tool invocation flows through a consistent path: The Hub mediates every interaction. This centralization enables:
  • Consistent authentication. Every request validates the JWT—there’s no path that bypasses verification.
  • User-scoped tools. The Hub loads only tools registered in the user’s connections. No global tool registry exists.
  • Origin validation. The agent only operates on domains you’ve explicitly allowed. A valid token from an unauthorized origin is rejected.

What This Enables

The security architecture enables capabilities that would otherwise be too risky: Cross-application tool invocation. A user can invoke tools across multiple internal applications because identity flows through the Hub with proper scoping. The tool in Application A can call the tool in Application B—but only for that authenticated user. External client access. Claude Desktop or VS Code can invoke browser-based tools because authentication and authorization happen at the Hub, not the browser. The external client connects to your user’s Hub, which routes requests to their browser tabs. Stateful conversations. Thread history persists across sessions because the Durable Object maintains state. Users can continue conversations—but only their own.

The Tradeoffs

This architecture makes specific tradeoffs: IDP dependency. Your identity provider’s availability is Char’s availability. There’s no fallback, no local accounts, no emergency access. No ambient context. The agent can’t “see” what the user sees. Page content must be explicitly exposed through tools. This limits what the agent can do without your developer effort. Per-user state. There’s no way to share state between users. Cross-user workflows require explicit coordination. Latency. Token validation and Hub routing add latency compared to direct tool invocation. For real-time use cases, this matters. These tradeoffs are intentional. The alternatives—storing credentials, sharing state, bypassing validation—would reintroduce the risks the architecture is designed to prevent.

Enterprise Security Features

Additional security controls are available on the Enterprise plan:
  • Rate limiting - Per-user and per-endpoint throttling with configurable thresholds
  • Audit logging - Centralized logging of all tool invocations for compliance review
  • Approval workflows - Human-in-the-loop for sensitive operations
  • Content guardrails - PII detection and prompt injection filtering
  • Kill switches - Instant disable of tools or connectors
The Hub-mediated architecture makes these controls straightforward to enable—they plug into the existing request flow without changing tool implementations.
Need these features? Contact us to discuss Enterprise pricing.

Further Reading