> ## Documentation Index
> Fetch the complete documentation index at: https://checkfu.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Trust and isolation

> Why a hijacked agent cannot leak a credential: structural security over permission scoping, from the sandbox boundary to the egress edge.

Checkfu assumes the workload is adversarial. End users author agents from day one, and
any agent that reads third-party content — email, issues, webhooks, web pages — is
processing attacker-controllable text. Prompt injection is treated as the default
condition, not an edge case: the harness inside a sandbox may be hijacked at any time,
so nothing inside the sandbox is trusted, and everything reachable from inside it must
have a bounded blast radius.

That assumption forces the design principle this page explains.

## Structural security over permission scoping

Most platforms answer "what if the agent is compromised?" with narrower permissions:
scope the token, shorten its life, restrict its audience. Scoping helps, but it encodes
an assumption about what a compromised agent *can't* do — and that assumption goes
stale as models get more capable. Checkfu's design law says the stronger thing:

> What must not leak is structurally absent, never merely denied.

A raw provider secret is never present in the sandbox, the event log, model context, or
harness configuration. There is no vault the agent can query, no environment variable
to read, no proxy that substitutes `$SECRET_NAME` into outbound traffic. When a control
fails, the failure mode is a denied action — never a disclosed secret.

## What this means concretely

**Credentials attach after the agent's involvement ends.** A
[Connection](/concepts/capabilities#connections)'s provider credential is held in the
selected custody boundary, behind an opaque handle. When a harness calls a credentialed
tool, Checkfu compiles the outbound request server-side and that boundary attaches the
secret at its outbound edge, outside the sandbox. The agent's process never holds a
secret it could exfiltrate — this is what "credential-free" means on every page of these
docs. See [Connections and catalog](/concepts/capabilities#object-model-and-custody)
for the object model behind that split.

There are two custody modes. Native accounts (D215) seal the record in Checkfu's own
store, addressed by the custody binding rather than by Workspace; authenticated
encryption binds it to that exact address, so a record moved between namespaces,
integrations, or handles fails to open. Checkfu also owns that outbound call: the
client refuses to follow redirects in code, and the worker is configured to reach
public destinations only — a pairing proved for every worker configuration rather than
asserted. Runtime-backed accounts keep encrypted records and refresh machinery inside
the selected IntegrationRuntime adapter; credential bytes may cross only that trusted
adapter and its provider request edge. What did not change in either mode is the claim
this page is about — no API response, event, log, sandbox, or model context can read
the credential back.

**Mounts carry no secrets.** The runtime handoff that gives a sandbox its Project
trees and memory directories is a credential-free mount plan: file bodies are resolved
by the platform against the Session's own lease, never by shipping a token into the
sandbox for the agent to use.

**The network boundary is declared before any credential exists.** Every Connection
carries between 1 and 32 default-deny [egress
rules](/concepts/capabilities#egress-rules) — host, port, path prefix, methods, and a
default-deny header allowlist — declared at authorization time. A request that matches
no rule is not sent, and routing- and authorization-bearing headers are denylisted so a
tool call cannot smuggle a credential or redirect itself.

**A SandboxProfile's network policy is a different boundary, and a weaker one.**
Connection egress rules are enforced where Checkfu makes the request, outside the
sandbox, so a hijacked workload cannot get around them. A SandboxProfile's own
`network_policy` constrains traffic the workload itself originates, and that is enforced by
a filter running alongside the workload. No provider Checkfu ships today grades it above
`advisory_filter`: it stops a confused agent, not a determined one. An `allowlist` policy
may demand the stronger grade with `required_egress_certification: "security_boundary"`,
and admission then refuses any provider whose exact revision does not advertise it — which,
until a certified provider revision exists, means such a SandboxProfile is refused outright rather
than quietly downgraded. Until then, treat workload-originated egress as unenforced when
you decide what data may enter a sandbox.

**An `allowlist` policy has conveniences, and they are abbreviations rather than modes.**
`allow_package_managers` and `allow_mcp_servers` are CMA's flag names, adopted so a
migrating config is copy-paste, but a flag never becomes a standing allowance: at
admission it **compiles** into the SandboxProfile revision's `allowed_hosts`, and enforcement,
the conformance tuple, and the Runner's own compile see exact hosts only. Three
consequences follow. The expansion is readable — a `GET` on the SandboxProfile shows every host
the flag granted, so there is no second, invisible allowance to audit. It is pinned — a
published version froze the hosts the preset catalog held at publication and records the
catalog version that produced them, so editing the catalog cannot reach a SandboxProfile that
already exists. And adopting a newer catalog is therefore a publish: a new SandboxProfile
version, a new derived image digest, a new network-policy hash. A preset update is a
policy change you can see and refuse, which is what "never a silent widening" has to
mean. `allow_package_managers` expands to the public registries for exactly the six
package ecosystems a SandboxProfile can declare; `allow_mcp_servers` deliberately expands to
**no workload host at all**, because a Checkfu sandbox never dials an MCP server itself —
every MCP call crosses the CapabilityGateway at plane authority, so adding third-party MCP
hostnames to the workload set would be a real grant wearing parity's clothes. The
practical consequence is worth knowing before you port a config: an `allowlist` has to
name somewhere to reach, so `allow_mcp_servers` **on its own**, with no hand-written
hosts and no `allow_package_managers`, is refused at admission rather than admitted as
an allowlist that reaches nothing.

**Customer code never enters the trusted plane.** Checkfu's Runner is data-plane
infrastructure, not workload code. Your harness, shims, install hooks, and
dependencies execute inside the sandbox under the workload threat model; the Runner
never dynamically imports customer code. Isolation strength is a property of who
authored the workload, not of a deployment stage or nominal sandbox tier. D243 fixes
the server-owned fact as `trusted | adversarial`, defaults missing provenance to
`adversarial`, and requires every realized enforcement axis plus either no network or
certified allowlist egress for that lane. A trusted Session may not later acquire
third-party executable content or steering; that requires a new adversarial Session.
Agent Versions and Session admission now freeze this classification, but concrete
provider placement does not yet enforce it (V-SBX-017). The complete frozen admission is
deployment-key authenticated, while public Session events omit private declaration actor/role
provenance. Current hosted support
must therefore not be read as proof that workload trust is enforced.

**The event log is the audit surface.** Every Session is an append-only event log —
tool calls, approvals, denials, and settlements are readable after the fact in order,
and [retention](/concepts/tenancy-and-governance#retention-model) is a property of
every stored entity, including zero-data-retention Workspaces where execution content
never reaches a durable sink.

## What scoping still does

Structural absence does not replace governance — it bounds what governance failures
can cost. PermissionAssignments still decide what a permitted agent may do; policies still route
sensitive actions through [ActionApprovals](/concepts/action-approvals); egress rules still shrink
where a call may go. The law only insists that none of these is the mechanism keeping
a secret safe from a hijacked workload. Scoping decides blast radius for *permitted*
actions; structure guarantees the *unpermitted* ones fail without disclosure.

<Note>
  The engineering-facing threat model behind this page — asset-by-asset blast radius,
  sandbox tier rules, and what remains under analysis — lives in the repository's
  `SECURITY.md`. This page states only what that document supports.
</Note>
