Skip to main content
Change of provenance

The repository or configuration that created this release differ from a previous release. View details.

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

Metadata

Release files for python-nsjail 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Change of provenance

The repository or configuration that created these release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Built distributions (wheels)

Table of built distributions (wheels) for python-nsjail 0.3.0
File Actions
python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl Python 3 none Linux musl 1.2+ x86-64 Details for python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl
python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl Python 3 none Linux musl 1.2+ ARM64 Details for python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl
python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl Python 3 none Linux glibc 2.34+ x86-64 Details for python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl
python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl Python 3 none Linux glibc 2.34+ ARM64 Details for python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl

Total release size: 9.7 MB

Release files / python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl
Size 3.1 MB
Tags Linux musl 1.2+ x86-64 Python 3
SHA-256 checksum
How to use checksums
27e95c885b256a973f4876d0e167732322d703afd6985826d5f8d7f1d4050a13
BLAKE2b-256 checksum
How to use checksums
640a9836b5fbcd2eb5c2a8cc2ca473392bae6e44b582e7c2a3e7f633ccdf6882
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 29, 2026.

Transparency log

Release files / python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL python_nsjail-0.3.0-py3-none-musllinux_1_2_aarch64.whl
Size 3.0 MB
Tags Linux musl 1.2+ ARM64 Python 3
SHA-256 checksum
How to use checksums
12e0c95e9cbbd2cf1c0b1f7a40131a6789e99fce7b8e0e149f41fee2a526c830
BLAKE2b-256 checksum
How to use checksums
fe68e942e7e58432ccfa54492bd6b76200bae77bfcd6470f16258736b3624eec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 29, 2026.

Transparency log

Release files / python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL python_nsjail-0.3.0-py3-none-manylinux_2_34_x86_64.whl
Size 1.9 MB
Tags Linux glibc 2.34+ x86-64 Python 3
SHA-256 checksum
How to use checksums
2b4c2fe78eefa1727fc11e2e1399b816af15bcadc0e8708660600b7cba48cd39
BLAKE2b-256 checksum
How to use checksums
0b72f786bd51443de9923fcc1f7f7a45402536ed941cfb9d095861c8303158df
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 29, 2026.

Transparency log

Release files / python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl

Change of provenance

This file belongs to a release with changed provenance: the repository or configuration that created the release files differ from that of a previous release.

We recommend inspecting the repository and configuration before proceeding. View details.

Download URL python_nsjail-0.3.0-py3-none-manylinux_2_34_aarch64.whl
Size 1.7 MB
Tags Linux glibc 2.34+ ARM64 Python 3
SHA-256 checksum
How to use checksums
558ed4dfeb6e476303ccd0971ad1833371cac13c3692bcb809484d5a3dcaf615
BLAKE2b-256 checksum
How to use checksums
40223f877430c8f10f199e2fc3471b6279ba67bd52c1913028f74b096f52a9f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 29, 2026.

Transparency log

Security for python-nsjail 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Change of provenance

The configuration that created this release differs from a previous release.

While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.

Select from 4 files

Attestation for python_nsjail-0.3.0-py3-none-musllinux_1_2_x86_64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page