# How CubeSandbox Security Proxy Performs Credential Injection: A Deep Dive into CubeProxy

> Learn how CubeSandbox security proxy injects credentials dynamically by intercepting outbound HTTP requests, matching egress policies, and injecting secrets as headers before forwarding traffic.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: deep-dive
- Published: 2026-07-09

---

**CubeSandbox injects credentials dynamically by intercepting outbound HTTP requests at the CubeProxy layer, matching them against egress policies defined in `network.rules`, and injecting rendered secret values as HTTP headers before forwarding traffic to external services.**

The CubeSandbox security proxy, known as **CubeProxy**, enforces Layer 7 egress policies to secure outbound traffic from sandboxed workloads. When a sandbox initiates an HTTP request, the proxy performs credential injection by fetching secrets from the **CubeMaster** secret store and attaching them as headers to authenticated requests. This process ensures that sensitive credentials never reside in sandbox code while enabling secure access to external APIs.

## The CubeProxy Credential Injection Architecture

CubeProxy operates as a **Layer 7 security proxy** within the CubeSandbox network-agent, specifically inside the **cubeegress** component. When a sandbox initiates an outbound HTTP request, the proxy evaluates the traffic against configurable egress policies that define both access controls and credential injection rules.

The injection mechanism relies on the **Inject** struct defined in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go), which specifies how secrets should be formatted and inserted into request headers. The proxy coordinates with the CubeMaster secret store to resolve secret values at runtime, ensuring that credentials remain confined to the sandbox's secure storage.

## Step-by-Step Credential Injection Process

When an HTTP request reaches CubeProxy, the system executes a four-phase injection workflow:

### Policy Lookup and Rule Matching

The proxy first reads the sandbox's egress policy from `network.rules`. Each rule contains a `match` section and an `action` section. The request's **SNI/host**, **method**, **path**, and **scheme** are compared against the rule's `Match` fields using case-insensitive comparison.

If a rule matches and `action.allow` is `true`, the proxy checks for credential injection requirements. When the matched rule's `action.inject` array is non-empty, the proxy proceeds to resolve and inject the specified credentials.

### Secret Resolution and Format Rendering

For each `Inject` entry in the rule, the proxy performs secret resolution through the sandbox-local secret API. The process involves:

- **Secret Lookup**: The `secret` field references a secret stored in the CubeMaster secret store. The proxy fetches the secret value via the sandbox-local secret API managed by CubeMaster.

- **Format Processing**: The `format` string (defaulting to `"${SECRET}"`) is processed by the `Inject.Render()` method in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go). This method substitutes the `${SECRET}` placeholder with the actual secret value, yielding the final header value.

The `EgressRuleInject` struct in [`network-agent/internal/service/types.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/service/types.go) mirrors the `Inject` definition for the gRPC service layer, ensuring consistent data models across components.

### Header Insertion and Request Forwarding

The actual header assembly occurs in [`network-agent/internal/cubeegress/wire.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/cubeegress/wire.go). The `renderInject` function orchestrates the final injection:

```go
// Inside network-agent/internal/cubeegress/wire.go (simplified)
for _, inj := range a.Inject {
    secretValue, err := secretStore.Get(inj.Secret) // fetch from sandbox secret store
    if err != nil { /* handle error */ }
    value := strings.ReplaceAll(inj.FormatOrDefault(), "${SECRET}", secretValue)
    outgoingReq.Header.Set(inj.Header, value) // header insertion
}

```

The proxy adds a new HTTP header named by `inject.header` (e.g., `Authorization`) with the rendered value to the outbound request. The modified request then proceeds to the external endpoint with the injected credentials, satisfying downstream authentication requirements without exposing secrets to the sandbox workload.

## Key Source Files and Implementation Details

The credential injection system spans multiple components within the TencentCloud/CubeSandbox repository:

- **sdk/go/policy.go**: Defines the credential injection data model and rendering logic through the `Inject` struct and `Render` method.

- **network-agent/internal/service/types.go**: Mirrors the `Inject` definition for the gRPC service layer via the `EgressRuleInject` struct.

- **network-agent/internal/cubeegress/wire.go**: Implements the actual injection logic through the `renderInject` function and request assembly.

- **CubeMaster/pkg/service/sandbox/**: Manages the secret retrieval APIs that provide the secret values referenced by injection rules.

The `Inject` struct in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go) defines the core data structure: `Header` specifies the target header name, `Secret` references the secret store key, and `Format` provides the template string for value rendering.

## Configuring Credential Injection in Practice

To enable credential injection, define an egress policy with the `inject` array populated. The following Go example demonstrates how to structure a policy using the CubeSandbox SDK:

```go
// SDK side – policy definition
policy := []cubesandbox.Rule{
    {
        Name: "Access private API",
        Match: cubesandbox.Match{
            Host: "api.private.example.com",
            Scheme: "https",
        },
        Action: cubesandbox.Action{
            Allow: true,
            Inject: []cubesandbox.Inject{
                {
                    Header: "Authorization",
                    Secret: "my-api-token",               // secret name in the sandbox store
                    Format: "Bearer ${SECRET}",           // optional, defaults to "${SECRET}"
                },
            },
        },
    },
}

```

When the sandbox issues an HTTPS request to `https://api.private.example.com/...`, CubeProxy automatically intercepts the traffic, retrieves the `my-api-token` secret from the CubeMaster store, renders the format string `Bearer ${SECRET}` with the actual token value, and injects the resulting `Authorization: Bearer <token>` header into the outbound request.

## Summary

- **CubeProxy** acts as the CubeSandbox security proxy, enforcing Layer 7 egress policies for all sandbox-initiated HTTP traffic.
- Credential injection occurs through a three-phase process: **policy matching**, **secret resolution**, and **header insertion**.
- The **`Inject`** struct in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go) defines the injection schema, while `Inject.Render()` handles format string substitution.
- **Secret resolution** relies on the CubeMaster secret store, accessed via the sandbox-local secret API.
- The **`renderInject`** function in [`network-agent/internal/cubeegress/wire.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/cubeegress/wire.go) performs the actual header assembly and attachment.

## Frequently Asked Questions

### How does CubeSandbox keep credentials secure during injection?

CubeSandbox stores all secrets in the **CubeMaster secret store**, which is inaccessible to sandbox workloads directly. The CubeProxy fetches secrets at runtime through the sandbox-local secret API, renders them into headers using the `Inject.Render()` method, and injects them into outbound requests. This ensures credentials never appear in sandbox code, environment variables, or process listings.

### What happens if the secret referenced in an inject rule does not exist?

If the `secretStore.Get(inj.Secret)` call in [`network-agent/internal/cubeegress/wire.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/cubeegress/wire.go) fails to retrieve the specified secret, the proxy handles the error according to the configured error policy. Typically, the request is blocked or rejected to prevent unauthorized access attempts, ensuring that unauthenticated requests cannot reach external services.

### Can I inject multiple headers using a single egress rule?

Yes. The `action.inject` field accepts an array of `Inject` objects, allowing you to specify multiple secrets and headers within a single rule. Each entry in the array is processed independently, fetching its respective secret and injecting it into the specified header before the request is forwarded.

### What is the default format string if I do not specify a format?

If the `format` field is omitted, the system defaults to `"${SECRET}"`. This means the secret value is injected directly into the header without additional prefixes or formatting. The `Inject.Render()` method in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go) substitutes the `${SECRET}` placeholder with the actual secret value to produce the final header content.