How CubeSandbox Applies Seccomp Filters for System Call Filtering in MicroVM Environments

CubeSandbox enforces system-call filtering inside Micro-VM containers by converting user-defined SysCall protobuf messages into OCI seccomp profiles and injecting them into the container runtime spec before the VM starts.

CubeSandbox, TencentCloud's containerized MicroVM runtime, leverages seccomp filters to restrict system calls within lightweight virtualized environments. By translating high-level security policies into kernel-level BPF programs, the platform ensures that each Micro-VM operates within a hardened syscall boundary. Understanding how CubeSandbox generates and applies these seccomp profiles reveals the mechanisms behind its isolation guarantees.

From Protobuf to BPF: The Seccomp Generation Pipeline

Parsing SysCall Requirements

The pipeline begins when the Cubelet API receives container creation requests containing cubebox.SysCall objects defined in the Cubebox protobuf specification. Each message specifies the syscall names to target, the desired action (allow, kill, errno), the error number to return when blocking, and optional argument matchers for fine-grained filtering.

Generating OCI Seccomp Options

The conversion logic resides in Cubelet/pkg/container/seccomp/seccomp.go. The GenOpt function transforms the protobuf list into a slice of specs.LinuxSyscall structures compatible with the OCI runtime specification.

// https://github.com/TencentCloud/CubeSandbox/blob/master/Cubelet/pkg/container/seccomp/seccomp.go
func GenOpt(_ context.Context, reqSysCalls []*cubebox.SysCall) oci.SpecOpts {
    // …convert each SysCall into specs.LinuxSyscall…
    return withSeccomp(sysCalls)
}

This function also constructs specs.LinuxSeccompArg structs for argument-based filtering, returning a oci.SpecOpts closure that modifies the container specification.

Layering Custom Rules on Default Profiles

Ensuring Baseline Protection

Before applying custom rules, CubeSandbox ensures a security baseline exists. The withSeccomp helper checks if the container spec already contains a seccomp profile. If not, it invokes cseccomp.DefaultProfile(s) (the Containerd helper) to create a default profile that blocks a broad set of dangerous syscalls.

Appending User-Defined Restrictions

The generated sysCalls slice is appended to the profile's Syscalls field, layering custom allow/deny rules atop the default protections. This merging strategy ensures that explicit user policies augment rather than replace the secure defaults.

// Example: creating a custom seccomp rule set for a container
reqSysCalls := []*cubebox.SysCall{
    {
        Names: []string{"open", "openat"},
        Action: uint32(cubebox.SysCallAction_ERRNO), // return EPERM
        Errno:  1,
        Args:   []*cubebox.SysCallArg{}, // no arg filtering
    },
    {
        Names: []string{"getrandom"},
        Action: uint32(cubebox.SysCallAction_ALLOW),
    },
}

// Generate the OCI spec option
seccompOpt := seccomp.GenOpt(context.Background(), reqSysCalls)

Injecting Seccomp into the Container Spec

Integration at Creation Time

The seccomp option is injected during container instantiation in Cubelet/services/cubebox/cube_container_create.go. The creation routine appends the generated option to the specification builder:

// https://github.com/TencentCloud/CubeSandbox/blob/master/Cubelet/services/cubebox/cube_container_create.go
specOpts = append(specOpts, seccomp.GenOpt(ctx, containerReq.Syscalls))

When the OCI spec is finally constructed, the Linux.Seccomp section contains the complete BPF filter that the Micro-VM runtime will enforce.

Runtime Enforcement in MicroVMs

Kernel-Level Filtering

Once the container launches within the Micro-VM (backed by Firecracker or KVM), the underlying runtime (via Containerd's seccomp implementation) loads the compiled BPF program into the kernel. All system calls made by the containerized process are vetted against this filter, with disallowed calls triggering the specified action—whether returning an error code, killing the process, or logging the violation.

Configuration Control

Operators can control seccomp behavior through the UnsetSeccompProfile flag defined in Cubelet/internal/cube/config/config.go. When enabled, this flag prevents the attachment of custom seccomp profiles, allowing unrestricted system call access for debugging or specialized workloads.

Summary

  • GenOpt converts cubebox.SysCall protobuf messages into OCI-compliant specs.LinuxSyscall structures.
  • DefaultProfile establishes a secure baseline by blocking dangerous syscalls before custom rules are applied.
  • cube_container_create.go integrates the seccomp option into the container specification during the creation workflow.
  • Kernel BPF enforcement ensures that Micro-VMs enforce the compiled seccomp filters at runtime via the underlying container runtime.

Frequently Asked Questions

What is the entry point for seccomp profile generation in CubeSandbox?

The entry point is the GenOpt function in Cubelet/pkg/container/seccomp/seccomp.go. This function receives a slice of cubebox.SysCall protobuf objects and returns an oci.SpecOpts that embeds the converted seccomp rules into the container specification.

How does CubeSandbox handle conflicting syscall rules?

CubeSandbox layers user-defined rules on top of a default security profile. The system appends custom LinuxSyscall entries to the profile's Syscalls slice, allowing explicit allow rules to override the default deny behavior while maintaining the baseline protections for dangerous system calls.

Can seccomp filtering be disabled for debugging?

Yes. The UnsetSeccompProfile configuration flag in Cubelet/internal/cube/config/config.go controls whether seccomp profiles are applied. When enabled, this flag prevents the injection of custom seccomp filters, allowing unrestricted system call access within the Micro-VM environments.

What runtime components actually enforce the seccomp filters?

The enforcement occurs at the kernel level through BPF programs loaded by Containerd's seccomp implementation. When the Micro-VM (operating via Firecracker or KVM) launches the container process, the kernel vets every system call against the compiled seccomp filter, applying the specified actions (allow, errno, kill) in real-time.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →