Trust boundaries
Browser to control plane
Browser to control plane
Browser sessions are cookie-based and signed. Private browser API handlers
check the session and resource ownership or project membership; public health,
published snapshots and token-authorized flows have separate policies. The
browser never receives a workspace token, and browser workspace and artifact
traffic is mediated by the control plane.
Control plane to workspace
Control plane to workspace
Each workspace has a random 32-byte bearer identity stored in a Kubernetes
Secret and mounted into the pod. It maps to one user and authenticates the
legacy artifact/conversation callback and daemon protocols. It is not sent to
the browser, but must not be treated as secret from root processes in that
user’s workspace. Automation machine APIs use separate scoped credentials. The
active
ARTIFACT_SCOPE is derived by the control plane and injected only into
the child shell process for that conversation, never pod-wide; it is a
caller-supplied scope, not a signed per-conversation capability.Workspace to artifact service
Workspace to artifact service
r5dchat artifacts presents the workspace identity plus x-artifact-scope.
The server resolves that scope and independently checks current project
membership or standalone-chat ownership on every list, read, upload,
overwrite, and delete. Knowing or substituting an identifier is not an
authorization grant. A workspace credential can select another scope already
authorized to that user; this is not isolation between that user’s chats.Workspace to cluster
Workspace to cluster
Tenant pods receive no service-account token, host path, runtime socket, or
host namespace.
automountServiceAccountToken is false and service links are
disabled, so a workspace has no ambient Kubernetes credential to use.Secrets at rest
Secrets at rest
Provider keys, custom headers, MCP headers, and OIDC client secrets are
AES-256-GCM encrypted with
SETTINGS_ENCRYPTION_KEY and stay in the control
plane.Outbound requests
Outbound requests
Provider, MCP, and OIDC destinations pass a guard that rejects non-HTTPS
URLs, credential-bearing URLs, private/loopback/link-local/metadata
addresses, and unsafe redirects, unless explicitly relaxed.
MCP Apps isolation
Interactive MCP Apps render untrusted server-provided HTML in sandboxed frames, using per-server origins on a dedicated registrable domain. A sibling subdomain of the product domain is not sufficient. Route these origins only to the separate sandbox listener, never the authenticated product Service. The chart’s sandbox has no service-account token and, with NetworkPolicy enabled, no egress. It receivesSETTINGS_ENCRYPTION_KEY for signed payloads,
so it is not a secret-free process. Browser content restrictions and pod network
policy are separate boundaries. See MCP Apps for deployment
requirements and verification before enabling it.
Workspace pod hardening
Workspace containers run as root on purpose, so agents can install packages for their task. Root is constrained:
The five allowed capabilities support container-local APT/dpkg operations:
SETUID/SETGID let APT use its _apt download sandbox, and
CHOWN/DAC_OVERRIDE/FOWNER let the package manager maintain files owned by
package users. Dropping them all breaks installation even with UID 0. These
capabilities also let workspace code change users and ownership inside its
container; they are not a per-command grant or an isolation boundary between
that user’s processes. No SYS_ADMIN, SYS_PTRACE, NET_ADMIN, NET_RAW, or
MKNOD is granted. Packages needing unavailable kernel/device/service privileges
are not supported; do not enable privileged mode to install them.
Use apt-get directly, without sudo. The home volume persists, but packages
installed outside /home/r5d do not survive container replacement. See
Workspace lifecycle for checks and
safe rollout behavior.
Enable a VM boundary with:
Workspace network boundary
WithnetworkPolicy.enabled: true and a NetworkPolicy-enforcing CNI, the chart
permits workspace traffic to:
- This release’s control-plane pods on TCP 3000 in the release namespace.
Artifact, conversation CLI and automation callbacks require this
exception.
WORKSPACE_CONTROL_PLANE_URLnormally uses the internal Service’sservice.port(default 80), which forwards to the container’s TCP 3000. The destination selector includes both chart name and release instance; it is not a namespace-wide allow rule. The reciprocal control-plane ingress rule permits same-namespace pods labelledapp.kubernetes.io/managed-by: r5d-chaton TCP 3000, even when public ingress is restricted to tunnel or ingress-controller pods. - DNS on UDP/TCP 53.
networkPolicy.workspaceDnsToselects the peers. Empty community defaults allow any destination on these ports; managed reference values restrict them to CoreDNS. This is not a DNS-name or DNS-content filter. - Public IPv4 when
networkPolicy.workspaceInternetEgress: true. The0.0.0.0/0rule excludesworkspaceInternetExcept: community defaults exclude RFC1918, loopback and link-local ranges; managed reference values additionally exclude CGNAT and the cluster’s public node addresses. Review the actual values for your cluster. There is no equivalent public IPv6 allow rule.
Reachability is not authorization
The callback exception is a destination/port boundary, not a URL-path allowlist. All routes on that listener are network-reachable;/api/health
intentionally returns {"ok":true} without authentication. That response alone
is neither a network-policy bypass nor unauthorized data access. Sensitive
handlers must still validate the appropriate browser session, workspace identity
and scope, or automation run capability. Source pod labels and access to the
internal Service do not authenticate an HTTP caller.
Test allowed callbacks separately from denied destinations and route
authorization. A negative network test must use a disposable, secret-free HTTP
canary outside the callback/DNS/public-IP allow rules, with the exact target and
request approved by the operator before the run. Do not substitute metadata,
Kubernetes, database, other tenants, or production services. Missing approval or
an unhealthy canary is an unrun/inconclusive test, not a pass.
A path-limited callback requirement would need a separate authenticated callback
listener or gateway, a complete method/path allowlist, and tests showing that
workspaces cannot bypass it through the product Service, pod IPs or public
origin. It must also preserve artifact/CLI/automation functionality with internet
egress disabled. The current chart does not implement or promise that
boundary; do not disable callbacks or widen namespace trust to approximate it.
File and artifact boundaries
There are two deliberately different boundaries:- Agent tools intentionally operate anywhere inside the container. The agent’s boundary is the pod itself, because installing and configuring software requires writing outside the home directory. The private workspace is not exposed through a user-facing file browser.
- Shared artifacts are remote control-plane resources. They are never mounted
at
/home/r5d, and an arbitrary private file is not published until the agent explicitly runsr5dchat artifacts push. Artifact paths reject traversal, backslashes, control characters, empty segments, and overlong input. Storage keys are opaque and unrelated to paths shown to collaborators.
fsGroup; workspace home PVCs never mount it. This separation prevents a
workspace process from bypassing artifact authorization with filesystem access.
Threats to plan for
Prompt injection
Prompt injection
Content the agent reads, whether a web page, a document, or an MCP tool
description, can contain instructions aimed at the model. Combining broad
web access with high-privilege MCP tools increases the blast radius. Give
MCP servers narrowly scoped credentials.
Malicious MCP servers
Malicious MCP servers
Tool definitions are model instructions. r5d.chat fingerprints them on
approval and surfaces later drift, but the initial trust decision is yours.
See MCP servers.
Resource exhaustion
Resource exhaustion
Agents can run expensive commands. Workspace CPU and memory limits bound a
single pod; namespace quotas bound the aggregate. Set both.
Data exfiltration through egress
Data exfiltration through egress
A workspace with internet egress can send private files or artifacts it is
authorized to pull anywhere. Set
networkPolicy.workspaceInternetEgress: false for sensitive tenants, accepting that agents can then no longer install
packages from the internet. DNS and control-plane callbacks still work; this
setting is not a complete exfiltration barrier. Scope authorization limits
which shared artifacts are available but cannot constrain what an authorized
model does with bytes after reading them.Unclaimed installation takeover
Unclaimed installation takeover
Before setup is claimed, anyone who reaches the URL can become the
administrator. Always set
SETUP_CLAIM_TOKEN before exposing an unclaimed
installation.Custom header exposure
Custom header exposure
Provider API keys are write-only, but custom headers are returned to the
authenticated owner so they remain editable. Treat header values as
user-visible secrets.
Hardening checklist
1
Set a claim token before exposure
SETUP_CLAIM_TOKEN in the Secret, claimed immediately after go-live.2
Keep the outbound guard strict
Leave
ALLOW_PRIVATE_EGRESS and ALLOW_INSECURE_HTTP at false unless a
specific endpoint requires otherwise.3
Use a VM runtime for untrusted tenants
workspace.runtimeClassName: kata or gvisor.4
Keep NetworkPolicy enabled
networkPolicy.enabled: true, and decide deliberately about
workspaceInternetEgress.5
Apply namespace quotas
Bound total pods, CPU, memory, and storage so one tenant cannot starve the
rest.
6
Use TLS end to end
Terminate HTTPS at the ingress and set
publicUrl to the https:// URL.7
Protect the recovery set
Store
SETTINGS_ENCRYPTION_KEY in a secrets manager and back it up with the
database and artifact PVC at one recovery point. Keep artifact storage
inaccessible to workspace pods.8
Keep a local admin account
Even with SSO enabled, as an identity-provider outage recovery path.
9
Update images regularly
The workspace image carries a large package surface; rebuild it to pick up
security updates.
Multi-tenancy guidance
- Trusted team
- Semi-trusted
- Untrusted
Colleagues under one policy. Default settings are appropriate: standard
container isolation, NetworkPolicy on, internet egress enabled.