> For the complete documentation index, see [llms.txt](https://docs.sonarsource.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sonarsource.com/sonarqube-server/server-installation/ai-agents/sandbox-runtime.md).

# Setting up the sandbox runtime

Install the gVisor sandbox runtime, or Kata Containers on OpenShift, so each SonarQube Server agentic job runs in its own isolated container. This page is for SonarQube Server 2026.5.

Every agentic job runs in its own container, and that container is sandboxed. The sandbox is not optional: it's the control that keeps code influenced by a large language model away from your host.

{% hint style="info" %}
See [Before you start](/sonarqube-server/server-installation/ai-agents/before-you-start.md) first. You need your hosts or cluster nodes to meet the architecture and platform requirements before you install the sandbox runtime.
{% endhint %}

SonarQube Server uses [gVisor](https://gvisor.dev/) as the sandbox runtime, in the form of its `runsc` runtime handler. gVisor intercepts system calls in user space instead of passing them to the host kernel, so a job that tries something destructive affects only its own sandbox.

gVisor uses its Systrap platform by default, which needs no hardware virtualization. That means you don't need `/dev/kvm`, so the sandbox runs on standard cloud instances and on hardened nodes where nested virtualization is disabled.

On OpenShift, gVisor is not available, and the agent runtimes are sandboxed with Kata Containers instead. See [#on-openshift](#on-openshift "mention").

## Why per-job isolation <a href="#why-per-job-isolation" id="why-per-job-isolation"></a>

| Risk                                                 | What the sandbox does about it                                                                                                 |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| A job runs a destructive command                     | The damage is contained in the sandbox. The root filesystem is read-only, and only the project and output folders are writable |
| A job tries to exfiltrate source code or credentials | Restricts outbound access to an explicit list of destinations, and blocks everything else                                      |
| A job consumes unbounded resources                   | Applies CPU, memory, and process limits per container. The Orchestrator fails a job that exceeds its time limit                |
| A job attempts to escape onto the host               | Handles system calls in user space, behind a second restrictive system call filter                                             |

Because each job gets its own container, container isolation is job isolation. There's no sharing between concurrent jobs to reason about.

## Fail-closed behavior <a href="#fail-closed" id="fail-closed"></a>

Sandbox selection is enforced, not advisory. There's no silent fallback to an unsandboxed container.

| Situation                                                                   | Result                                                                                                                                                                                                         |
| --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The sandbox runtime is not registered                                       | The container refuses to start, reporting an unknown runtime                                                                                                                                                   |
| The runtime is registered but the image architecture doesn't match the host | The container crashes on start with `exec format error`                                                                                                                                                        |
| On OpenShift, the Kata `RuntimeClass` is missing                            | The Helm chart fails to install. If you set `OpenShift.skipAgentRuntimeClassCheck` to `true`, the chart installs, but the agent runtime pods are rejected with `RuntimeClass "kata" not found` and never start |

If jobs won't start, this is the first thing to check. See [Troubleshooting](/sonarqube-server/server-installation/ai-agents/troubleshooting.md).

## On Kubernetes <a href="#on-kubernetes" id="on-kubernetes"></a>

On Kubernetes, gVisor is installed on the nodes and selected per pod through a `RuntimeClass`. The Helm chart creates the `RuntimeClass` and sets it on the agent runtime pods for you.

You have two ways to get `runsc` onto the nodes.

### Provisioning the nodes yourself <a href="#provisioning-yourself" id="provisioning-yourself"></a>

This is the recommended approach for production. Install `runsc` on the nodes that run agentic jobs, configure containerd with the `runsc` runtime handler, then deploy with the chart's installer turned off:

```yaml
gvisor:
  enabled: true
  installer:
    enabled: false
```

Use this approach when your platform team manages node configuration, when your cluster policy doesn't allow privileged workloads, or in air-gapped environments where you supply `runsc` yourself.

On managed Kubernetes services, use the provider's own mechanism instead of installing gVisor by hand. On Google Kubernetes Engine, GKE Sandbox provides gVisor natively and exposes the same `RuntimeClass`.

### Using the chart installer <a href="#chart-installer" id="chart-installer"></a>

The chart can install gVisor for you with a DaemonSet. This is convenient for self-managed clusters and for evaluation.

```yaml
gvisor:
  enabled: true
  installer:
    enabled: true
```

{% hint style="warning" %}
The installer is privileged. It runs with host access to change the containerd configuration on each node, which requires a namespace that permits privileged pods, and permission to read and modify every node object in the cluster. Review it against your cluster policy before you enable it.
{% endhint %}

The installer downloads and verifies `runsc`, writes the sandbox configuration, registers the runtime handler with containerd, and validates the configuration before restarting containerd. If any step fails, it restores the previous containerd configuration. It labels a node as ready for sandboxed workloads only after it confirms `runsc` is working there.

The installer is only for self-managed nodes. Don't use it on a managed service that provides its own mechanism.

### Choosing which nodes run jobs <a href="#node-selection" id="node-selection"></a>

By default, the chart schedules agentic jobs onto nodes labeled for gVisor, and the installer targets all nodes. To confine jobs to a subset of your cluster, label those nodes and set a node selector. To install on every node, leave the installer's node selector empty.

{% hint style="danger" %}
A `RuntimeClass` is cluster-scoped, so its name must be unique across the cluster. If you run more than one SonarQube Server release in the same cluster, give each one a different `runtimeClassName`. Otherwise the second release fails to install, because the name is already owned by the first.
{% endhint %}

For the full list of values, see [Deploying with the Helm chart](/sonarqube-server/server-installation/ai-agents/customizing-helm-chart.md).

## On OpenShift <a href="#on-openshift" id="on-openshift"></a>

gVisor is not available on OpenShift. CRI-O cannot use the `runsc` runtime, and the chart's gVisor installer supports containerd only. On OpenShift, the Helm chart runs the Hunter Agent and Remediation Agent runtimes with Kata Containers instead, through a `RuntimeClass` that the OpenShift sandboxed containers operator provides.

### Installing the OpenShift sandboxed containers operator <a href="#openshift-operator" id="openshift-operator"></a>

Install the OpenShift sandboxed containers operator before you deploy the chart. The chart does not create the `RuntimeClass`, and the installation fails if it's missing.

Choose the `RuntimeClass` that matches your worker nodes:

| Worker nodes                                                                                           | `RuntimeClass`                |
| ------------------------------------------------------------------------------------------------------ | ----------------------------- |
| Bare-metal Red Hat Enterprise Linux CoreOS (RHCOS) workers, on premises or on AWS bare-metal instances | `kata`                        |
| Cloud VMs on AWS, Azure, or Google Cloud                                                               | `kata-remote`, with peer pods |

For the setup steps on bare metal and with peer pods, see the [OpenShift sandboxed containers documentation](https://docs.redhat.com/en/documentation/openshift_sandboxed_containers/).

### Setting the Helm values <a href="#openshift-helm-values" id="openshift-helm-values"></a>

```yaml
OpenShift:
  enabled: true
  agentRuntimeClassName: kata
  skipAgentRuntimeClassCheck: false
```

| Value                                  | Description                                                                                                                                                                                                                                  |
| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OpenShift.enabled`                    | Set to `true` to enable OpenShift. The chart then ignores the `gvisor.*` values and does not deploy the gVisor installer, so you do not need to change them                                                                                  |
| `OpenShift.agentRuntimeClassName`      | The `RuntimeClass` for the agent runtimes. Defaults to `kata`. Set it to `kata-remote` for peer pods                                                                                                                                         |
| `OpenShift.skipAgentRuntimeClassCheck` | Defaults to `false`, so the chart checks that the `RuntimeClass` exists. Set it to `true` when the installing credentials cannot read cluster-scoped `RuntimeClass` objects, or when the `RuntimeClass` is created together with the release |

{% hint style="danger" %}
An empty `OpenShift.agentRuntimeClassName` turns off the sandbox: the agent runtimes run under the cluster's default container runtime, and the chart installs without an error. The only signal is a warning in the post-install notes. This is the only exception to the fail-closed behavior described on this page, and it is not recommended.
{% endhint %}

For the rest of the OpenShift configuration, see [Customizing Helm chart](/sonarqube-server/server-installation/on-kubernetes-or-openshift/customizing-helm-chart.md#enabling-openshift).

## Service mesh <a href="#service-mesh" id="service-mesh"></a>

This section applies to Helm chart deployments, on both Kubernetes and OpenShift.

The chart does not inject the standard Istio sidecar into the sandboxed agent runtimes, so by default they stay outside the service mesh. To add them to the mesh, set `istio.meshSidecar.enabled` to `true` in addition to `istio.enabled`. The agent runtimes then get their own mTLS identity.

This also requires a network plugin that enforces NetworkPolicies. Without one, the agent runtime's own port stays reachable on the pod network without authentication.

## On a Docker host <a href="#on-docker" id="on-docker"></a>

On a Linux host running Docker Engine, install gVisor on the host and register `runsc` as a Docker runtime. The agent runtime containers then request it by name.

{% hint style="info" %}
Registering a Docker runtime changes the Docker daemon configuration and requires a daemon restart. Membership of the `docker` group is not enough: you need root access on the host.
{% endhint %}

Two sandbox settings are worth knowing about, because they affect how jobs behave:

* The sandbox uses the host network stack, which avoids the sandbox network layer interfering with name resolution. Isolation between the job and your network still comes from the outbound restrictions described in [Before you start](/sonarqube-server/server-installation/ai-agents/before-you-start.md)
* The sandbox provides a bounded writable overlay, which caps how much disk a job can use. Docker's own controls cannot cap it

Keep the gVisor version consistent across your hosts and your cluster nodes. When you update it in one place, update it everywhere in the same change.

## Next step <a href="#next-step" id="next-step"></a>

With the sandbox runtime registered, provision shared storage. See [Setting up shared storage](/sonarqube-server/server-installation/ai-agents/shared-storage.md).

## Related pages <a href="#related-pages" id="related-pages"></a>

* [Before you start](/sonarqube-server/server-installation/ai-agents/before-you-start.md)
* [Deploying with the Helm chart](/sonarqube-server/server-installation/ai-agents/customizing-helm-chart.md)
* [Troubleshooting](/sonarqube-server/server-installation/ai-agents/troubleshooting.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.sonarsource.com/sonarqube-server/server-installation/ai-agents/sandbox-runtime.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
