> ## Documentation Index
> Fetch the complete documentation index at: https://docs.katakate.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Security & networking

> Non-root execution, Linux capabilities, and egress control

This page covers sandbox security posture and how to configure it via the API.

## Non-root execution

* `pod_non_root` (boolean, default false): Run the Pod as non-root (UID/GID/FSGroup 65532). Applies pod-wide filesystem ownership.
* `container_non_root` (boolean, default false): Run the main container as non-root (UID 65532) and disallow privilege escalation.

Guidance:

* Enable both flags for consistent non-root behavior and fewer permission surprises when writing to volumes.
* Some package managers (e.g., Alpine `apk add`) require root. To run `apk add` inside the container, you have options:
  * Use `before_script` with a base image that already includes needed tools, or
  * Temporarily run the main container with root by leaving `container_non_root` disabled for setup, or
  * Build a custom image with dependencies pre-installed (recommended for production reproducibility).

Example (non-root):

```json theme={null}
{
  "name": "nr-example",
  "image": "alpine:latest",
  "pod_non_root": true,
  "container_non_root": true
}
```

Example (install packages first as root, then lock down egress):

```json theme={null}
{
  "name": "setup-then-lock",
  "image": "alpine:latest",
  "before_script": "apk add --no-cache curl git",
  "egress_whitelist": ["203.0.113.0/24"]
}
```

## Linux capabilities

Default policy: drop ALL capabilities. Add back only what you need. If you specify `cap_drop` explicitly, you override the default; to keep `drop ALL` and add back minimal caps, leave `cap_drop` unset and only use `cap_add`.

* `cap_drop` (string\[]): Capabilities to drop. If omitted, `ALL` is dropped by default.
* `cap_add` (string\[]): Capabilities to add back.
* `allow_privilege_escalation`: always set to `false`.
* Seccomp profile: `RuntimeDefault`.

Examples:

Minimal add-back while still dropping ALL by default:

```json theme={null}
{
  "name": "caps-minimal",
  "image": "alpine:latest",
  "cap_add": ["CHOWN"],
  "cap_drop": null
}
```

Override drop policy (not recommended unless you know why):

```json theme={null}
{
  "name": "caps-custom",
  "image": "alpine:latest",
  "cap_drop": ["NET_RAW"],
  "cap_add": []
}
```

### Common capability requirements

When you encounter permission errors in `before_script` or during container execution, you may need to add specific capabilities. Here are common use cases:

**Package managers (apt-get, yum, dnf):**

```json theme={null}
{
  "name": "install-packages",
  "image": "ubuntu:22.04",
  "cap_add": ["SETUID", "SETGID", "CHOWN", "DAC_OVERRIDE"],
  "before_script": "apt-get update && apt-get install -y git curl"
}
```

* `SETUID`/`SETGID`: Required for package managers to drop privileges during installation
* `CHOWN`: Needed for changing file ownership during package installation
* `DAC_OVERRIDE`: Allows bypassing file permission checks (needed for installing packages)

**Alpine package manager (apk):**

```json theme={null}
{
  "name": "alpine-packages",
  "image": "alpine:latest",
  "cap_add": ["SETUID", "SETGID", "CHOWN"],
  "before_script": "apk add --no-cache git curl"
}
```

**File operations requiring ownership changes:**

```json theme={null}
{
  "name": "file-ops",
  "image": "alpine:latest",
  "cap_add": ["CHOWN", "FOWNER"],
  "before_script": "chown -R user:group /some/path"
}
```

**Network operations (raw sockets, packet capture):**

```json theme={null}
{
  "name": "network-tools",
  "image": "alpine:latest",
  "cap_add": ["NET_RAW", "NET_ADMIN"]
}
```

<Warning>
  Adding `NET_RAW` or `NET_ADMIN` significantly reduces isolation. Only use when absolutely necessary for network debugging or specialized tools.
</Warning>

<Info>
  **Best practice**: Pre-build custom images with dependencies installed rather than installing packages at runtime. This improves security, reproducibility, and startup time.
</Info>

## Network isolation and egress lockdown

### Ingress isolation (Default: Enabled)

**All inter-VM communication is blocked by default** to prevent sandbox-to-sandbox access. This provides strong isolation between different sandboxes running in the same cluster.

**Key points:**

* **Ingress blocking**: VM sandboxes cannot communicate with each other by default
* **Administrative access preserved**: `kubectl exec` and `k7 shell` still work normally (they use the Kubernetes API, not pod networking)
* **System services allowed**: Traffic from `kube-system` namespace is permitted for cluster functionality
* **No configuration needed**: This security feature is enabled by default for all sandboxes

### Egress lockdown and whitelisting

Use `egress_whitelist` to control outbound traffic. The policy is applied after the container becomes Ready so `before_script` runs with open egress.

Behavior:

* Omit `egress_whitelist`: egress open (external internet allowed).
* `[]`: full egress block (no DNS resolution; no outbound IPs).
* `["CIDR", ...]`: allow only listed CIDR blocks; DNS is blocked.

Examples:

Full isolation (no inter-VM communication, no external access):

```json theme={null}
{ "name": "fully-isolated", "image": "alpine:latest", "egress_whitelist": [] }
```

Partial isolation (no inter-VM communication, but external internet allowed):

```json theme={null}
{ "name": "partial-isolation", "image": "alpine:latest" }
```

Whitelist specific external services (avoid public DNS resolvers):

```json theme={null}
{
  "name": "egress-restricted",
  "image": "alpine:latest",
  "egress_whitelist": ["10.0.0.5/32"]
}
```

<Info>
  **Network Policy Details:**

  * **Ingress**: Blocked by default (inter-VM isolation) - system services and kubectl exec still work
  * **DNS**: When egress is locked down, DNS resolution is blocked by default (no CoreDNS exception)
  * **Administrative access**: `kubectl exec`, `k7 shell`, and API operations bypass network policies
</Info>

<Warning>
  Do not whitelist public DNS resolver IPs (e.g., 1.1.1.1, 8.8.8.8). Because K7's `egress_whitelist` is CIDR-only (no L7/port rules), allowing those IPs enables outbound DNS (UDP/TCP 53) and DNS-over-HTTPS (443), which can be used for exfiltration. If you want an egress deny with whitelisting, prefer whitelisting only your own egress proxy/gateway IP and enforce DNS/DoH policy at that proxy. Later, whenever we integrate Cilium (a roadmap feature), it will be much simpler as you'll be able to whitelist domain names directly.
</Warning>

### Mitigations when DNS is blocked

* Use IP/CIDR whitelisting only (no domains post-lockdown)
* Pre-resolve/fetch in `before_script` (runs before lockdown with open egress)
* If you must allow DNS temporarily, consider an operational override at cluster level (not provided by K7 config)
