Secure sensitive customer data
Braintrust’s servers and employees do not require access to your data plane for it to operate successfully. That means that you can protect it behind a firewall or VPN and physically isolate it from access. When you use the Braintrust web application, it communicates directly with the data plane (via CORS), and the data does not flow through any intermediate systems (the control plane, or otherwise) before reaching your browser. While the data plane does send metrics and status telemetry to the control plane, it does not send logs, traces, or customer data. Because of this architecture, our self-hosted customers do not generally list us as a subprocessor. Like any third-party software, it is important that you establish the appropriate controls to ensure that your deployment is secure, and Braintrust can help you do so. Ultimately, the goal of the control plane and data plane split is to provide you with the highest levels of security and compliance.Grant browser permissions
This is a client-side step performed by end-users in their browser, not a Terraform or Helm setting. The only deployment-side control is the Data plane is on a private network toggle in organization settings.
Local Network Access is a Chrome security feature that protects users from malicious websites accessing resources on their private networks. For more information, see Chrome’s Private Network Access documentation.
Configure organization authorization
By default, any Braintrust organization can authenticate against your self-hosted data plane. Use the following settings to restrict access to specific organizations. You can find an organization’s ID in the Braintrust UI. See Find your organization ID.- AWS
- GCP / Azure
Set Only organizations whose IDs appear in the list can use the deployment. Leave the variable empty (the default) to impose no restriction. Organization IDs must be UUIDs, not organization names.
allowed_org_ids to a comma-separated list of Braintrust organization UUIDs (available in Terraform module v5.8.1 or later):If
braintrust_org_name is set to a specific organization name, include that organization’s ID in allowed_org_ids for forward compatibility.Configure URL security
Braintrust backends validate user-supplied URLs (such as webhook targets and external endpoints invoked by scorers or tools) before making outbound requests, to prevent server-side request forgery (SSRF). By default, requests that resolve to private or reserved IP ranges are allowed and logged with a warning rather than blocked. To block them, set the URL request mode toreject.
- AWS
- GCP / Azure
The following Terraform variables configure URL security (available in module v5.8.1 or later):To allow a specific internal CIDR while warning on other private ranges:
To block all requests to private or reserved addresses:
Enable audit headers
Audit headers are a legacy feature, retained for existing integrations. They predate Braintrust’s audit logging feature, which is the recommended way to track administrative actions and data access. Audit headers are enabled per request by the API client rather than through Terraform or Helm.
x-bt-enable-audit: true header in your API request.
When this header is present, the API response will include the following additional headers:
x-bt-audit-user-id: The ID of the user who made the request (based on the provided API key or impersonation).x-bt-audit-user-email: The email of the user who made the request.x-bt-audit-normalized-url: A normalized representation of the API endpoint path that was called. Path parameters like object IDs are replaced with placeholders (for example,/v1/project/[id]).x-bt-audit-resources: A JSON-encoded, gzipped, and base64-encoded string containing a list of Braintrust resources (like projects, experiments, datasets, etc.) that were accessed or modified by the request. Each resource object includes itstype,id, andname.
x-bt-audit-resources header requires specific parsing due to its encoding.
Here’s an example of how to parse it using the Python SDK:
Enable S3 attribute-based access control
On AWS, IAM policies for the S3 buckets the module manages grant access by bucket ARN. To base access decisions on bucket tags instead, set theenable_s3_bucket_abac Terraform variable to true (available in Terraform module v5.3.0 or later). This supports tag-based governance or service control policies that gate access by resource tags.
s3:TagResource, s3:UntagResource, and s3:ListTagsForResource permissions. This variable is disabled by default.
Pod security contexts and storage limits
This section applies to GCP and Azure deployments using the Helm chart (6.2.2+).
emptyDir size limits, and writable /tmp volumes for the API and all Brainstore roles (brainstore.reader, brainstore.fastreader, brainstore.writer). By default, the Braintrust manifests don’t set these fields, so configure them only if you want to enforce a stricter security posture.
Some hardened clusters require these settings. They enforce admission policies, often written as Common Expression Language (CEL) constraints, that reject any workload unless its pods declare a non-root, read-only security context and bounded storage. GKE Autopilot is one such environment, so a deployment that doesn’t set these fields is blocked until you add them.
The settings in this section apply to any GCP or Azure Helm deployment. For a complete reference, see the
examples/google-autopilot-cel/values.yaml example in the Helm chart, which configures them for GKE Autopilot.Security contexts
Set a container-levelsecurityContext on the API and each Brainstore role to enforce a read-only root filesystem, disallow privilege escalation, and drop all Linux capabilities:
podSecurityContext (for example, api.podSecurityContext or brainstore.reader.podSecurityContext) to apply settings such as runAsNonRoot or fsGroup to the entire pod. Both contexts are omitted from the rendered manifests unless you set them.
Writable /tmp volumes
When you enablereadOnlyRootFilesystem: true, the container can no longer write to its root filesystem. Enable a tmpVolume for each affected component to mount a writable emptyDir at /tmp:
Ephemeral storage and cache volume limits
Each Brainstore role accepts anephemeralStorage budget and a volume.sizeLimit for its cache emptyDir:
ephemeralStorage.requestsets the pod-local storage budget that GKE Autopilot reserves.ephemeralStorage.limitsets the corresponding cap.volume.sizeLimitcaps the cacheemptyDir. Match it toobjectStoreCacheFileSizeso the cache cannot exceed its allotted space.