This feature is currently in public preview and is not recommended for production use. During the preview, the proxy and network features are only available in the us-was-1 region.
The Blaxel proxy intercepts outbound HTTPS requests from the sandbox and injects headers, body fields, and secrets server-side.
import { SandboxInstance } from "@blaxel/core";
const sandbox = await SandboxInstance.create({
name: "my-sandbox",
image: "blaxel/base-image:latest",
region: "us-was-1",
network: {
proxy: {
routing: [
{
destinations: ["api.stripe.com"],
headers: {
"Authorization": "Bearer {{SECRET:stripe-key}}",
"Stripe-Version": "2024-12-18.acacia",
},
secrets: {
"stripe-key": "sk_live_...",
},
},
],
},
},
});
Code inside the sandbox calls api.stripe.com normally - the proxy intercepts the request, injects the Authorization and Stripe-Version headers with the resolved secret, and forwards it. The sandbox never sees the raw API key.
Body injection (POST requests)
await SandboxInstance.create({
name: "body-injection",
network: {
proxy: {
routing: [
{
destinations: ["api.stripe.com"],
headers: {
"Authorization": "Bearer {{SECRET:stripe-key}}",
},
body: {
"api_key": "{{SECRET:stripe-key}}",
},
secrets: {
"stripe-key": "sk_live_...",
},
},
],
},
},
});
The proxy merges body fields into outbound POST/PUT/PATCH JSON payloads. User-sent fields are preserved; injected fields are added alongside them.
Multiple routing rules
await SandboxInstance.create({
name: "multi-route",
network: {
proxy: {
routing: [
{
destinations: ["api.stripe.com"],
headers: { "Authorization": "Bearer {{SECRET:stripe-key}}" },
secrets: { "stripe-key": "sk_live_..." },
},
{
destinations: ["api.openai.com"],
headers: { "Authorization": "Bearer {{SECRET:openai-key}}" },
secrets: { "openai-key": "sk-proj-..." },
},
],
bypass: ["*.s3.amazonaws.com"],
},
},
});
Secrets are scoped per rule — the Stripe key is never injected into OpenAI requests and vice versa.
Global catch-all rule
await SandboxInstance.create({
name: "global-auth",
network: {
proxy: {
routing: [
{
destinations: ["*"],
headers: {
"X-Global-Auth": "Bearer {{SECRET:global-key}}",
},
secrets: {
"global-key": "token-xyz",
},
},
],
},
},
});
The ["*"] destination matches all proxied traffic.
Proxy bypass
Domains listed in bypass skip the proxy tunnel entirely (direct connection):
await SandboxInstance.create({
name: "bypass-only",
network: {
proxy: {
bypass: ["*.s3.amazonaws.com", "169.254.169.254"],
},
},
});
S3 and metadata endpoint traffic goes direct; everything else routes through the proxy.
Secret interpolation
Secrets are referenced in headers and body values using the {{SECRET:name}} syntax:
"Authorization": "Bearer {{SECRET:api-token}}" → "Bearer tok_live_abc123"
"X-Multi": "{{SECRET:part-a}}-{{SECRET:part-b}}" → "ALPHA-BETA"
"X-Plain": "no-secret-here" → "no-secret-here" (unchanged)
- Multiple
{{SECRET:...}} placeholders can appear in a single value
- Secrets are resolved server-side by the proxy — the sandbox runtime never sees raw secret values
- Secrets are write-only: the
secrets field is stripped from API responses
- Secrets are scoped per routing rule: a secret defined on route A cannot be resolved by route B
- User code inside the sandbox can also send
{{SECRET:name}} in its own request headers or body — the proxy will resolve them if the secret exists on the matching route
Reading proxy config from an existing sandbox
After creation or retrieval, network config is available as typed model attributes:
import { SandboxInstance } from "@blaxel/core";
const sandbox = await SandboxInstance.get("my-sandbox");
const network = sandbox.spec.network;
if (network?.proxy?.routing) {
for (const route of network.proxy.routing) {
console.log(route.destinations);
console.log(route.headers["Authorization"]);
}
if (network.proxy.bypass) {
console.log(network.proxy.bypass);
}
}
if (network?.allowedDomains) {
console.log(network.allowedDomains);
}