How CubeEgress Handles TLS Inspection in CubeSandbox: MITM Re-Signing and Root CA Baking
CubeEgress implements TLS inspection by acting as a Man-In-The-Middle (MITM) proxy that terminates outbound TLS connections, re-signs traffic with a baked-in root CA, and forwards decrypted payloads to external destinations while maintaining end-to-end TLS semantics for sandboxed workloads.
CubeEgress is the egress-side MITM proxy responsible for all outbound TLS traffic from CubeSandbox workloads. According to the TencentCloud/CubeSandbox source code, it handles TLS inspection through a two-phase mechanism that combines build-time certificate authority injection with runtime transparent proxy re-signing. This architecture allows security teams to inspect HTTPS traffic for policy enforcement without modifying application code.
The TLS Inspection Architecture
CubeEgress operates as a transparent proxy that intercepts outbound TLS connections initiated by sandboxed workloads. When a workload attempts to establish a TLS session with an external server, CubeEgress terminates the original connection, validates the upstream server's certificate, and establishes a new TLS session toward the real destination. For the client-side connection, it presents a certificate signed by the CubeEgress root CA, which is pre-installed in the sandbox's trust store during image build.
Root CA Baking: Establishing Trust Inside the Sandbox
The foundation of CubeEgress TLS inspection relies on ensuring that every process inside the sandbox trusts the CubeEgress root certificate. This is achieved through a build-time operation called "CA Baking."
Build-Time CA Injection
The Bake function in CubeMaster/pkg/templatecenter/cube_egress_ca/cube_egress_ca.go handles the injection of the CubeEgress root CA into the sandbox root filesystem. This routine appends the CA certificate to standard bundle files such as etc/ssl/certs/ca-certificates.crt and places copies into distribution-specific anchor directories. The implementation guarantees that the CA is present before the sandbox starts, eliminating the need for host-side update-ca-certificates execution.
Handling Distroless and Scratch Images
For minimal images such as distroless or scratch containers that lack standard certificate bundles, the baking process seeds a fresh bundle containing only the CubeEgress CA. This ensures that even containers without a traditional operating system trust hierarchy can validate the re-signed certificates presented by CubeEgress.
import "github.com/TencentCloud/CubeSandbox/CubeMaster/pkg/templatecenter/cube_egress_ca"
func bakeCA(rootfs string, caPEM []byte) error {
res, err := cube_egress_ca.Bake(rootfs, caPEM)
if err != nil {
return err
}
if !res.Baked {
// No write was needed – the CA was already present.
return nil
}
// res.TargetsWritten indicates how many bundle / anchor files were updated.
return nil
}
Transparent TLS Re-Signing: The Proxy Mechanism
Once the CA is baked into the sandbox, CubeEgress performs transparent TLS re-signing at runtime to enable inspection of encrypted traffic.
Connection Termination and Validation
When intercepting outbound TLS handshakes, CubeEgress uses a custom tls.Config configured with the baked root CA in its RootCAs pool. The proxy validates the target server's certificate using standard TLS verification before decrypting the payload. The relevant TLS configuration is populated in CubeMaster/pkg/service/httpservice/cube/template_from_image.go at lines 251-252, where the transport's TLSClientConfig is initialized.
Certificate Re-Issuance
After validating the upstream server, CubeEgress generates a new leaf certificate signed by the baked CubeEgress CA for the client-side connection. Because the sandbox's trust store contains the CubeEgress root, the client application sees a valid certificate chain, allowing the connection to proceed without certificate warnings. The proxy then forwards the decrypted payload to the real destination over a new TLS session.
transport := &http.Transport{
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: &tls.Config{
// The baked root CA is loaded into a CertPool elsewhere.
RootCAs: pool,
},
}
client := &http.Client{Transport: transport}
The proxy logic handles the connection hijacking and certificate replacement:
func (p *Proxy) handleTLS(w http.ResponseWriter, r *http.Request) {
// 1. Establish TLS to the real destination.
upstreamConn, err := tls.Dial("tcp", r.Host, p.upstreamTLSConfig)
// 2. Generate a leaf cert signed by the baked CA for the client.
leaf, err := p.ca.SignLeaf(r.Host)
// 3. Hijack the client connection, present the leaf cert, and pipe traffic.
clientConn, _ := w.(http.Hijacker).Hijack()
tlsServer := tls.Server(clientConn, &tls.Config{Certificates: []tls.Certificate{leaf}})
go io.Copy(upstreamConn, tlsServer) // client → upstream
go io.Copy(tlsServer, upstreamConn) // upstream → client
}
Security and Policy Enforcement
This dual-mechanism approach allows CubeEgress to inspect clear-text HTTPS traffic for policy enforcement, logging, and content scanning while preventing workloads from bypassing inspection. Because the only trusted root in the sandbox is the CubeEgress CA, any external certificate must be re-issued by the proxy, effectively forcing all TLS traffic through the inspection point.
Summary
- Root CA Baking injects the CubeEgress certificate authority into sandbox images at build time via
CubeMaster/pkg/templatecenter/cube_egress_ca/cube_egress_ca.go. - Transparent Re-Signing terminates TLS connections, validates upstream certificates, and re-issues leaf certificates signed by the baked CA.
- Trust Enforcement ensures sandboxes trust only the CubeEgress CA, making MITM-based TLS inspection possible without application modifications.
- Configuration uses custom
tls.ConfigwithRootCAspopulated inCubeMaster/pkg/service/httpservice/cube/template_from_image.go.
Frequently Asked Questions
How does CubeEgress prevent sandboxes from bypassing TLS inspection?
CubeEgress prevents bypass by controlling the root of trust within the sandbox. During image build, the Bake function seeds the CubeEgress CA as the only trusted root certificate in the sandbox filesystem. When workloads attempt TLS connections, they can only validate certificates signed by this CA, which only CubeEgress can issue. This forces all TLS traffic through the proxy for inspection.
What happens to the original server certificate during CubeEgress TLS inspection?
CubeEgress validates the original server certificate using its own TLS client configuration configured with standard root CAs. After validation, it decrypts the traffic for inspection, then creates a new TLS session to the destination using a separate encrypted connection. The original certificate is never presented to the sandboxed workload; instead, the workload receives a re-signed leaf certificate generated by CubeEgress.
Where is the CubeEgress root CA stored in the sandbox filesystem?
The CubeEgress root CA is stored in standard system certificate locations depending on the base image. For most distributions, it is appended to /etc/ssl/certs/ca-certificates.crt and copied to distro-specific anchor directories. For distroless or scratch images, a fresh certificate bundle containing only the CubeEgress CA is seeded at the standard path during the build process.
Does CubeEgress TLS inspection work with distroless containers?
Yes, CubeEgress TLS inspection supports distroless containers through specialized CA seeding. The baking logic in cube_egress_ca.go detects minimal images and creates a fresh certificate bundle containing only the CubeEgress CA, ensuring that even containers without standard SSL libraries or operating system certificate stores can validate the re-signed certificates.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →