Credential Injection
Credential injection lets a Sandbox call an upstream API with a long-lived provider credential that never enters the Sandbox. The egress proxy resolves the credential from a Kubernetes Secret and rewrites the matching outbound request just before it leaves the cluster, so the workload and the agent code only ever see their own placeholder header.
Injection is configured by the platform administrator through a SecurityProfile (namespaced) or
GlobalSecurityProfile (cluster-scoped). Both share the same tokenTransformation action and the same Secret-based
credential source.
Prerequisitesâ
Credential injection is enforced by the egress proxy in the TrafficProxy data plane, so the target Sandbox must run the
traffic-proxy runtime. Declare it on the Sandbox, or on the SandboxTemplate or SandboxSet it derives from, as
described in Enroll a Sandbox:
spec:
runtimes:
- name: traffic-proxy
For pooled Sandboxes, declare the runtime in the template. A sidecar cannot be injected when a Sandbox is claimed from
the pool, so a pool whose template omits traffic-proxy produces Sandboxes where injection never takes effect.
Without the traffic-proxy runtime, outbound requests bypass the egress proxy entirely: the SecurityProfile is never
applied, the placeholder header leaves the Sandbox unchanged, and the upstream call fails authentication. Confirm the
sidecar is running before relying on credential injection.
How It Worksâ
- The administrator stores the upstream credential in a Kubernetes Secret.
- A
SecurityProfileselects the Sandbox Pods and defines atokenTransformationrule whosecredentialRef.secretpoints at that Secret. - On each matching outbound request, the egress proxy reads the Secret, renders the target header value, and replaces the request header before forwarding it upstream.
Because the credential is resolved per request at the proxy, it is not written into the Pod spec, the Sandbox environment, or Sandbox metadata, and rotating the Secret takes effect without restarting the Sandbox.
Create the Credential Secretâ
For an ApiKey transformation, the Secret carries the credential under the data key apiKey:
apiVersion: v1
kind: Secret
metadata:
name: example-api-credentials
namespace: agent-demo
type: Opaque
stringData:
apiKey: "sk-example-1234567890"
Configure a SecurityProfileâ
The profile below selects Pods labeled app: agent and injects the Secret value into the authorization header of
HTTPS requests to api.example.com under the /v1/ prefix:
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: example-api-credentials
namespace: agent-demo
spec:
selector:
matchLabels:
app: agent
rules:
- name: inject-example-api-key
match:
- domains:
- api.example.com
schemes:
- https
paths:
- type: Prefix
value: /v1/
actions:
tokenTransformation:
type: ApiKey
failStrategy: Block
credentialRef:
secret:
name: example-api-credentials
apiKey:
targetHeaders:
names:
- authorization
value:
template: "Bearer {{ .Token }}"
Key fields:
credentialRef.secret.nameis the Secret to read.credentialRef.secret.namespaceis optional: when omitted, aSecurityProfileuses its own namespace and aGlobalSecurityProfileuses the selected Pod's namespace. Set exactly one ofsecretorcredentialProviderundercredentialRef; this page coverssecretonly.apiKey.targetHeaders.nameslists the request headers to overwrite.targetHeaders.celselects header names dynamically instead.apiKey.value.templaterenders the replacement value.{{ .Token }}is the credential resolved from the Secret, and the template can also read.Header,.Request,.Pod,.Profile,.Rule, and.Inputs.failStrategydefaults toBlock(fail closed): if the Secret cannot be resolved, the request is rejected rather than forwarded without a credential.
Fine-grained, Per-sandbox Injectionâ
Injection is scoped at two levels. The profile's selector chooses which Sandboxes (Pods) it applies to, so each
Sandbox only receives the credentials selected for it. Within a Sandbox, a rule's match block scopes injection to
specific traffic, so one Secret is only ever attached to the requests that should carry it:
domainsis required and supports an exact host (api.example.com) or a single leading wildcard (*.example.com).paths,methods,schemes,ports,headers, andqueryParamsfurther restrict the match. Fields inside onematchentry are ANDed; multiplematchentries are ORed.
This per-host granularity mirrors the E2B per-host request transforms model, where transforms are keyed by the
destination host. When you drive Sandboxes through the E2B interface, you express the same host-level scoping in the
network.rules field:
{
"templateID": "code-interpreter",
"network": {
"allowOut": ["api.example.com"],
"rules": {
"api.example.com": [
{"transform": {"headers": {"X-Tenant": "demo"}}}
]
}
}
}
Use the two mechanisms together by host: the administrator-defined SecurityProfile injects the credential into the
selected hosts, while the E2B per-host transform sets non-sensitive, host-scoped headers for the same destination.
The native E2B per-host transform stores header values verbatim, and tokenTransformation is rejected in inline E2B
rules. Per-host request transforms are therefore for non-credential headers only; always inject credentials from a
Secret through a SecurityProfile. See E2B Network Controls.
Clean Upâ
Delete the profile to stop injection:
$ kubectl delete securityprofile example-api-credentials --namespace agent-demo
Deleting the profile stops rewriting requests but does not revoke a credential that was already issued. Keep Secret values short-lived where possible and rotate them at the provider for emergency response.