Skip to main content

NexCTF Sandbox

A NexCTF plugin that checks answers by running Python: a code runner that tests players' programs against test cases, and a script checker that validates answers with a function you write. Every run happens in a throwaway microsandbox microVM, booted for the submission and removed right after.

ty uv Ruff Python 3.15

Quick Start

Add the plugin to NexCTF's NEXCTF_PLUGINS and restart it; NexCTF installs it from PyPI and applies its migrations:

NEXCTF_PLUGINS=nexctf-sandbox==1.0.0

Each plugin release supports one NexCTF minor version, so upgrade the two together:

nexctf-sandbox NexCTF
1.0.x 0.12.x

The NexCTF process that checks submissions boots the microVMs, so it needs read and write access to /dev/kvm. Nothing else: the network setting is enforced by microsandbox's own network stack, with no extra capability or root.

With NexCTF's compose.yml, that goes on the app service, e.g. in a compose.override.yml. /dev/kvm belongs to the host's kvm group, which the image's unprivileged user has to join; get its id with stat -c %g /dev/kvm:

services:
  app:
    devices:
      - /dev/kvm
    group_add:
      - "993"  # the kvm group id on the host
    environment:
      NEXCTF_PLUGINS: nexctf-sandbox==1.0.0

Then, on a question, pick the solution type runner or script.

Features

🏃 Code runner

  • Runs the player's Python 3 code against up to 20 test cases, feeding each one's input on stdin
  • Accepted only when every case's stdout matches the expected output, whitespace stripped
  • A crash or a non-zero exit fails the case
  • All the cases of a submission share one microVM, run one after the other
  • For questions with a code input

✅ Script checker

  • Validates the answer with your own Python function, check(answer, team_id, team_fields) -> bool
  • Hands the checker the team's custom fields, typed, private ones included: per-team flags and seeds work out of the box
  • The starter checker lists the team custom fields that exist
  • Checkers written without team_fields keep working as they are
  • For questions with an input, text or code input

Writing a checker

The checker is a function named check that returns True to accept the answer. team_id is the team's id as a string, or None; team_fields maps each team custom field name to its value (int, bool or str), and a key is missing when the team left the field empty. Declare team_fields only if you need it:

import hashlib


def check(answer: str, team_id: str | None, team_fields: dict) -> bool:
    seed = team_fields.get("seed", "")
    flag = "FLAG{" + hashlib.sha256(seed.encode()).hexdigest()[:16] + "}"
    return answer.strip() == flag

The checker runs in its own microVM, with the base image's Python and the network access set below.

Settings

Under Settings → Plugins → Sandbox:

Setting Default
Base image python:3.14-slim; any OCI image with python3 on PATH
vCPUs 1
Memory 256 MiB, plus the root disk
Root disk 64 MiB, in RAM
Network access disabled; internet for public addresses and the host's DNS, all for unfiltered egress, the host's own network included
Max concurrent microVMs 8, across all challenges; takes effect after a restart

Development

The tests stub out the microVMs and need no database. NexCTF is a dev dependency installed from git (currently its v0.12.0 tag).

uv sync
uv run pytest
uv run ruff check . && uv run ruff format --check . && uv run ty check .

The live tests boot real microVMs and skip without /dev/kvm; the one reaching the internet also skips when the host has none. Run them on the host that will check submissions before an event:

uv run pytest -m live

To load a local checkout in a dev NexCTF, add its path to NEXCTF_PLUGINS in NexCTF's .env.dev.override, then restart task dev:backend.

Metadata

Release files for nexctf-sandbox 1.0.0

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

Source distribution (sdist)

Source distribution for nexctf-sandbox 1.0.0
File Size Uploaded
nexctf_sandbox-1.0.0.tar.gz 11.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nexctf-sandbox 1.0.0
File Interpreter ABI Platform
nexctf_sandbox-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 26.4 kB

Release files / nexctf_sandbox-1.0.0.tar.gz

Download URL nexctf_sandbox-1.0.0.tar.gz
Size 11.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f61c15a54d017bf66e83ca5d9840a62af44c564524f876a74f4d19f02f960f9d
BLAKE2b-256 checksum
How to use checksums
9306178930fdb2945c133880d1813bdb3765b57a8180906f16cbb16d783c2be4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 11, 2026.

Transparency log

Release files / nexctf_sandbox-1.0.0-py3-none-any.whl

Download URL nexctf_sandbox-1.0.0-py3-none-any.whl
Size 14.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b69a59e036c549aaa61387b3ddeead1e71c6de6cf5655afea03eda054f9a7a20
BLAKE2b-256 checksum
How to use checksums
24378fb5ab485d69148ab13c170a532737b04eb0d2266917b14c56e660bdde47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 11, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

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