# How to Configure CubeEgress Domain Allowlists and Egress Security Policies in CubeSandbox

> Learn how to configure CubeEgress domain allowlists and egress security policies with CubeSandbox. Master L7 domain-based rules for enhanced network security.

- Repository: [Tencent Cloud/CubeSandbox](https://github.com/TencentCloud/CubeSandbox)
- Tags: how-to-guide
- Published: 2026-07-03

---

**CubeSandbox implements a two-layer egress control system where CubeVS handles L3/L4 CIDR filtering and CubeEgress enforces L7 domain-based rules, requiring explicit `deny_out` rules when using domain allowlists to pass validation.**

TencentCloud/CubeSandbox protects outbound traffic through a sophisticated architecture that separates IP-level filtering from application-layer policy enforcement. Configuring **CubeEgress domain allowlists and egress security policies** allows you to restrict sandbox environments to specific external APIs while safely injecting credentials and maintaining comprehensive audit trails.

## Understanding the Two-Layer Egress Architecture

CubeSandbox employs a dual-layer approach to secure outbound connections:

- **Layer 3/4 (CubeVS)**: An eBPF-based data plane that manages raw IP routing, NAT, and CIDR-based egress filtering through `allow_out` and `deny_out` lists.
- **Layer 7 (CubeEgress)**: An OpenResty/NGINX proxy that intercepts HTTP/HTTPS traffic redirected from CubeVS, applies per-domain or per-path rules, injects credentials, and writes audit logs.

## Configuring Domain Allowlists (`allow_out`)

The `allow_out` configuration accepts both IPv4 CIDR strings and DNS names (e.g., `api.openai.com` or `*.example.com`). When a rule's **match** contains an `SNI`, `Host`, or `Scheme` referencing a domain, CubeSandbox automatically adds that domain to `allow_out`, ensuring the underlying eBPF layer permits the traffic.

### Validation Requirements

According to the validation logic in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go) (lines 60-71), domain-based allowlists only validate when paired with a deny-all configuration. The `validateAllowOutDomainsRequireDenyAll` function enforces that either all other egress is denied (default "deny-all" mode) or `0.0.0.0/0` is explicitly placed in `deny_out`. If violated, the API returns a 400 error with the message defined in `allowOutDomainRequiresDenyAll`.

## Defining Egress Security Policies (L7 Rules)

L7 rules consist of match conditions and actions defined in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go). The **Match** struct supports optional `SNI`, `Host`, `Method`, `Path`, and `Scheme` fields—all fields are AND-ed, while `Method` accepts multiple values (OR-ed). The **Action** struct specifies `Allow` (with optional `Inject` objects) or explicit denial (`Allow: false`), plus an optional `Audit` string for logging labels.

```go
// Match holds rule match conditions.
type Match struct {
    SNI    string   `json:"sni,omitempty"`
    Host   string   `json:"host,omitempty"`
    Method []string `json:"method,omitempty"`
    Path   string   `json:"path,omitempty"`
    Scheme string   `json:"scheme,omitempty"`
}

// Inject injects a credential header on an allowed HTTPS request.
type Inject struct {
    Header string `json:"header"`
    Secret string `json:"secret"`
    Format string `json:"format,omitempty"`
}

// Action is a rule action.
type Action struct {
    Allow  bool     `json:"allow"`
    Inject []Inject `json:"inject,omitempty"`
    Audit  string   `json:"audit,omitempty"`
}

// Rule is one L7 egress rule.
type Rule struct {
    Name   string `json:"name"`
    Match  Match  `json:"match"`
    Action Action `json:"action"`
}

```

When `Action.Allow` is `true`, CubeEgress forwards the request and injects any headers defined in `Inject`. If `false`, it returns HTTP 403 before the request leaves the cluster.

## Policy Propagation Flow

Configuration flows through the system as follows:

1. **Sandbox creation**: The user passes a `network` block (`allow_out`, `deny_out`, `rules`) via the API or SDK.
2. **CubeMaster**: Stores the configuration and pushes it to the **network-agent**.
3. **network-agent**: Converts the high-level policy into a `cubeegress.PolicyInput` payload and calls `PutPolicy`. See the implementation in [`network-agent/internal/service/cubeegress_push.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/service/cubeegress_push.go) (lines 13-73).
4. **CubeVS**: Installs CIDR allow/deny lists. For every DNS query matching a domain in `allow_out`, CubeVS learns resolved IPs and adds them to the CIDR list automatically.
5. **CubeEgress**: Receives the policy via its admin API, compiles the Lua rule set, and filters HTTP/HTTPS traffic redirected from CubeVS via the TPROXY iptables chain.

## Implementation Examples

### Go SDK Configuration

```go
import (
    "github.com/TencentCloud/CubeSandbox/sdk/go"
)

func createSandbox() (*cubesandbox.Sandbox, error) {
    cfg := &cubesandbox.CubeNetworkConfig{
        // Allow only the OpenAI API domain; everything else is denied.
        AllowOut: []string{"api.openai.com"},
        DenyOut:  []string{"0.0.0.0/0"}, // required when domains are used
        Rules: []cubesandbox.Rule{
            {
                Name: "OpenAI credential injection",
                Match: cubesandbox.Match{
                    SNI: "api.openai.com",
                },
                Action: cubesandbox.Action{
                    Allow: true,
                    Inject: []cubesandbox.Inject{
                        {
                            Header: "Authorization",
                            Secret: "sk-xxxxxxxxxxxxxxxxxxxx",
                            // ${SECRET} will be substituted with the secret value.
                        },
                    },
                    Audit: "openai-call",
                },
            },
        },
    }

    // `Create` also accepts `AllowInternetAccess: false` to start from a deny‑all state.
    return client.Sandbox.Create(
        cubesandbox.SandboxCreateOpts{
            Network: cfg,
            AllowInternetAccess: false,
        })
}

```

The validation in [`policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/policy.go) guarantees this call succeeds; if `DenyOut` is omitted, the API returns a 400 error.

### Python SDK Configuration

```python
from cubesandbox import CubeSandbox

cs = CubeSandbox()

sandbox = cs.sandbox.create(
    allow_internet_access=False,
    network={
        "allow_out": ["api.openai.com"],
        "deny_out":  ["0.0.0.0/0"],
        "rules": [
            {
                "name": "OpenAI credential injection",
                "match": {"sni": "api.openai.com"},
                "action": {
                    "allow": True,
                    "inject": [{"header": "Authorization",
                                "secret": "sk-xxxxxxxxxxxxxxxxxxxx"}],
                    "audit": "openai-call"
                }
            }
        ],
    },
)

```

### Retrieving Active Policies

```go
// Assuming `client` is a configured network‑agent client.
pol, err := client.Egress.GetPolicy(context.Background(), sandboxIP)
if err != nil {
    log.Fatalf("failed to fetch policy: %v", err)
}
fmt.Printf("Current CubeEgress policy: %+v\n", pol)

```

The returned JSON mirrors the [`policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/policy.go) structure and represents the exact payload CubeEgress uses internally.

## Safety Checks and Constraints

CubeSandbox enforces strict validation to prevent misconfigurations:

- **Domain-only allowlists require deny-all**: Enforced by `validateAllowOutDomainsRequireDenyAll` to ensure domains are not accidentally whitelisted while other traffic is permitted.
- **Wildcard restrictions**: Only the `*.` prefix is allowed (e.g., `*.example.com`). The `isDomainAllowOutTarget` function rejects any other `*` placement in the string.
- **Credential isolation**: Secrets are stored only in CubeMaster and injected by CubeEgress just before the outbound request leaves the host, never exposing credentials to sandbox code.

## Summary

- CubeSandbox uses **CubeVS** for L3/L4 CIDR filtering and **CubeEgress** for L7 domain and path-based rules.
- **Domain allowlists** (`allow_out`) require explicit `deny_out: ["0.0.0.0/0"]` to pass validation enforced in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go).
- **L7 rules** support matching on `SNI`, `Host`, `Method`, `Path`, and `Scheme`, with actions for allowing, denying, or injecting credentials via the `Inject` struct.
- Policies propagate from the SDK through CubeMaster to the **network-agent**, which pushes them to CubeEgress via the admin API defined in [`network-agent/internal/service/cubeegress_push.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/network-agent/internal/service/cubeegress_push.go).
- **Wildcard domains** must use the `*.` prefix format, and credential injection occurs securely at the proxy layer without exposing secrets to sandbox code.

## Frequently Asked Questions

### What is the difference between CubeVS and CubeEgress?

**CubeVS** operates at the network layer (L3/L4) using eBPF to filter traffic based on IP CIDRs and manage NAT, while **CubeEgress** operates at the application layer (L7) as an OpenResty/NGINX proxy that inspects HTTP/HTTPS requests, enforces domain policies, injects headers, and generates audit logs. CubeVS handles the initial allow/deny decisions for IP traffic, while CubeEgress applies fine-grained rules to HTTP-specific attributes like SNI and Host headers.

### Why do I need to set `deny_out` to `0.0.0.0/0` when using domain allowlists?

The validation logic in [`sdk/go/policy.go`](https://github.com/TencentCloud/CubeSandbox/blob/main/sdk/go/policy.go) (lines 60-71) requires this configuration to prevent security gaps. Domain-based allowlists only make sense in a "deny-all" mode where all other traffic is explicitly blocked. Without `0.0.0.0/0` in `deny_out`, the API returns a 400 error with the message `allowOutDomainRequiresDenyAll`, ensuring that domain whitelisting does not accidentally coexist with permissive network access.

### How does credential injection work in CubeEgress?

When a request matches a rule with `Action.Allow: true` and contains `Inject` objects, CubeEgress adds the specified headers to the outbound request just before it leaves the host. The **secret values** are stored in CubeMaster and never exposed to the sandbox code; only the proxy performs the injection using the format specified in the `Inject` struct's `Header` and `Format` fields.

### Can I use wildcards in domain allowlists?

Yes, but only with the `*.` prefix format (e.g., `*.example.com`). The `isDomainAllowOutTarget` function validates that wildcards appear only at the beginning of the domain string. Any other placement of `*` in the string is rejected during validation, ensuring that wildcard matching remains predictable and secure.