Skip to main content

Prebuilt google nsjail executable file packaged as Python wheels with simple Python APIs

Project description

python-nsjail

Prebuilt nsjail executable file packaged as Python wheels with simple Python APIs

CI codecov GitHub tag PyPI version PyPI - Python Version PyPI - Implementation PyPI - Status PyPI - License

Overview

Just install and use — no compilation required. python-nsjail provides prebuilt nsjail binaries as Python wheels, making the powerful Linux namespace sandbox immediately available.

System Requirements

  • OS: Linux only
  • Kernel: Linux 5.10+ (some nsjail features require newer kernel syscalls)
  • Permissions: Using nsjail requires CAP_SYS_ADMIN or root
  • Python: Python 3.9+
  • C++ Runtime: libstdc++ (pre-installed on standard Linux distributions; see Platform Compatibility below)

Platform Compatibility

Platform libc Compatible With CPU Requirement
manylinux_2_34_x86_64 glibc 2.34 Ubuntu 22.04+, Debian 12+, RHEL 9+ x86-64-v2* (SSE4.2, POPCNT)
manylinux_2_34_aarch64 glibc 2.34 ARM64 systems ARM64 (v8+)
musllinux_1_2_x86_64 musl 1.2 Alpine Linux 3.17+, other musl-based x86-64-v2* (SSE4.2, POPCNT)
musllinux_1_2_aarch64 musl 1.2 Alpine Linux ARM64 3.17+ ARM64 (v8+)

⚠️ C++ Runtime Requirement:
The nsjail binary is written in C++ and requires libstdc++ \

  • manylinux wheels: libstdc++ is pre-installed on all glibc-based distributions (Ubuntu, Debian, RHEL, Fedora, etc.) \
  • musllinux wheels: libstdc++ is pre-installed on Alpine 3.17+ \
  • Minimal containers (scratch, distroless): you may need to install libstdc++ manually

⚠️ x86-64-v2 Note:
The x86_64 wheels are built with manylinux_2_34 containers which use x86-64-v2 by default. This requires a CPU from ~2010 or later (supports SSE4.2 and POPCNT instructions). Most modern systems support this. If you need to run on older x86-64 hardware (pre-2010), please use the source distribution or build from source.

Installation

pip install python-nsjail

Now run:

nsjail --help

You got nsjail installed!

Verify Installation

nsjail --help
nsjail-status

nsjail-status displays installation details including binary location and nsenter availability.

Where is the nsjail binary?

The nsjail command is installed as a console script in your environment's bin/ directory (e.g., .venv/bin, ~/.local/bin, or /usr/local/bin). The underlying binary is bundled with the Python package.

For development, after building the wheel with python setup.py bdist_wheel, the binary will be at src/nsjail/bin/nsjail.

Getting the Binary Path from Python

If you need the nsjail binary path in your scripts:

from nsjail import bundled_nsjail

nsjail_path = bundled_nsjail()
print(nsjail_path)  # /absolute/path/to/nsjail

Or use locate_nsjail() which respects the NSJAIL environment variable and checks system paths:

from nsjail import locate_nsjail

nsjail_path = locate_nsjail()  # Returns path with priority: env var > system > bundled

Priority:

  1. NSJAIL environment variable (if set)
  2. System paths: /usr/local/bin, /usr/bin
  3. Bundled binary (fallback)

Python API

The library provides simple functions for creating nsjail subprocesses. Both synchronous and asynchronous APIs are available.

Basic Usage

Async API:

import asyncio
import subprocess
from nsjail import async_create_nsjail, NsjailOptions

async def main():
    # Basic usage - output to terminal
    proc = await async_create_nsjail(
        command=["/bin/echo", "hello"],
        options=NsjailOptions(chroot="/"),
    )
    await proc.wait()

    # Capture output
    proc = await async_create_nsjail(
        command=["/bin/cat", "/etc/hostname"],
        options=NsjailOptions(chroot="/", user="nobody"),
        stdout=subprocess.PIPE,
    )
    output = await proc.stdout.read()
    print(output.decode())

asyncio.run(main())

Sync API:

import subprocess
from nsjail import create_nsjail, NsjailOptions

# Capture output synchronously
proc = create_nsjail(
    command=["/bin/echo", "hello"],
    options=NsjailOptions(chroot="/"),
    stdout=subprocess.PIPE,
)
output, _ = proc.communicate()
print(output.decode())

Using nsenter

Enter an existing container's namespace with async_create_nsenter:

import asyncio
import subprocess
from nsjail import async_create_nsenter

async def main():
    # Run 'ip addr' inside container 1234's network namespace
    proc = await async_create_nsenter(
        target_pid=1234,
        namespaces=["net"],
        command=["ip", "addr"],
        stdout=subprocess.PIPE,
    )
    output = await proc.stdout.read()
    print(output.decode())

asyncio.run(main())

Inspect Command Arguments

For debugging or testing, you can build the nsjail arguments without executing:

from nsjail import build_nsjail_args, NsjailOptions

args = build_nsjail_args(
    options=NsjailOptions(chroot="/", user="nobody"),
    config_file="/path/to/config.cfg",
)
print("nsjail", *args, "--", "/bin/echo", "hello")
# Output: nsjail --chroot / --user nobody --config /path/to/config.cfg -- /bin/echo hello

Passing Additional Arguments

All *args and **kwargs are passed directly to the underlying subprocess creation functions:

import subprocess
from nsjail import async_create_nsjail, NsjailOptions

# Pass cwd, env, and other subprocess.Popen / asyncio.create_subprocess_exec arguments
proc = await async_create_nsjail(
    command=["/bin/sh", "-c", "echo $FOO"],
    options=NsjailOptions(chroot="/"),
    stdout=subprocess.PIPE,
    cwd="/tmp",
    env={"FOO": "value"},
)

NsjailOptions

Configure nsjail with NsjailOptions:

from nsjail import NsjailOptions

options = NsjailOptions(
    chroot="/srv/jail",           # Chroot directory
    user=65534,                    # Run as user (UID)
    group=65534,                   # Run as group (GID)
    hostname="sandbox",            # Set hostname
    cwd="/tmp",                    # Working directory inside jail
    env={"HOME": "/tmp"},          # Environment variables
    bindmount=["/tmp:/tmp"],       # Read-write bind mounts
    bindmount_ro=["/lib:/lib"],    # Read-only bind mounts
    tmpfsmount=["/tmp"],           # Temporary filesystem mounts
    time_limit=60,                 # Wall time limit in seconds
    memory_limit=512,              # Memory limit in MB
    # ... see NsjailOptions for all options
)

Environment Variable

NSJAIL - Override the nsjail binary path (for Python API only)

export NSJAIL=/custom/path/to/nsjail

Supports ~ and $VAR expansion:

export NSJAIL=~/local/bin/nsjail
export NSJAIL=$XDG_DATA_HOME/nsjail/bin/nsjail

Use Cases

Sandbox Untrusted Code

Execute untrusted Python code with resource limits:

from nsjail import create_nsjail, NsjailOptions
import subprocess

proc = create_nsjail(
    command=["python3", "-c", "print('Hello from sandbox')"],
    options=NsjailOptions(
        chroot="/srv/jail",
        user="nobody",
        time_limit=5,           # 5 second timeout
        memory_limit=128,       # 128MB memory limit
        bindmount_ro=["/usr/lib", "/usr/lib64"],
    ),
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
)
stdout, stderr = proc.communicate()
print(stdout.decode())

Isolated Network Testing

Test network behavior in an isolated environment:

from nsjail import async_create_nsjail, NsjailOptions

async def test_network():
    proc = await async_create_nsjail(
        command=["curl", "https://example.com"],
        options=NsjailOptions(
            isolate_network=True,  # Disable network
        ),
    )
    await proc.wait()
    # curl will fail due to network isolation

Containerized Testing

Run tests in a clean environment:

from nsjail import create_nsjail, NsjailOptions

proc = create_nsjail(
    command=["pytest", "tests/"],
    options=NsjailOptions(
        chroot="/tmp/test-env",
        bindmount_ro=["/usr", "/lib"],
        tmpfsmount=["/tmp"],
    ),
)

API Reference

Async Functions

  • async_create_nsjail(command, options=None, config_file=None, *args, **kwargs) - Create async nsjail subprocess
  • async_create_nsenter(target_pid, namespaces, command, options=None, *args, **kwargs) - Create async nsenter subprocess

Sync Functions

  • create_nsjail(command, options=None, config_file=None, *args, **kwargs) - Create sync nsjail subprocess
  • create_nsenter(target_pid, namespaces, command, options=None, *args, **kwargs) - Create sync nsenter subprocess

Helper Functions

  • build_nsjail_args(options=None, config_file=None) - Build nsjail command-line arguments
  • build_nsenter_args(target_pid, namespaces, options=None) - Build nsenter command-line arguments

Classes

  • NsjailOptions - nsjail configuration options
  • NsenterOptions - nsenter configuration options

Locator Functions

  • locate_nsjail() - Find nsjail binary (respects NSJAIL env var)
  • bundled_nsjail() - Get bundled nsjail binary path

Building from Source

For development or building from source, see CONTRIBUTING.md.

For Developers

If you're working on a clone of this repository and want to run/debug nsjail locally, you need to build the wheel first to generate the nsjail binary:

python setup.py bdist_wheel
# or: python -m build --wheel
# or: uv build --wheel

This compiles the nsjail binary and places it at src/nsjail/bin/nsjail, which is required for the package to function in place.

License

  • nsjail: Apache-2.0 (see google/nsjail)
  • python-nsjail packaging: Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl (3.1 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl (3.0 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl (1.9 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ x86-64

python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl (1.7 MB view details)

Uploaded Python 3manylinux: glibc 2.34+ ARM64

File details

Details for the file python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 27e95c885b256a973f4876d0e167732322d703afd6985826d5f8d7f1d4050a13
MD5 58a2a521d13748d20564aa750bdf2026
BLAKE2b-256 640a9836b5fbcd2eb5c2a8cc2ca473392bae6e44b582e7c2a3e7f633ccdf6882

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl:

Publisher: python-package.yml on tanbro/python-nsjail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 12e0c95e9cbbd2cf1c0b1f7a40131a6789e99fce7b8e0e149f41fee2a526c830
MD5 07b43cf1e93bfaf07398f7fd15ca8cc6
BLAKE2b-256 fe68e942e7e58432ccfa54492bd6b76200bae77bfcd6470f16258736b3624eec

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl:

Publisher: python-package.yml on tanbro/python-nsjail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 2b4c2fe78eefa1727fc11e2e1399b816af15bcadc0e8708660600b7cba48cd39
MD5 906548d7f2a136decdf35ebf01542058
BLAKE2b-256 0b72f786bd51443de9923fcc1f7f7a45402536ed941cfb9d095861c8303158df

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl:

Publisher: python-package.yml on tanbro/python-nsjail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl.

File metadata

File hashes

Hashes for python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl
Algorithm Hash digest
SHA256 558ed4dfeb6e476303ccd0971ad1833371cac13c3692bcb809484d5a3dcaf615
MD5 ae578ea30763b50af671ed0ef0d40ea7
BLAKE2b-256 40223f877430c8f10f199e2fc3471b6279ba67bd52c1913028f74b096f52a9f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl:

Publisher: python-package.yml on tanbro/python-nsjail

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page