Changelog
All notable changes to the Network Sandbox Engine (NSE) project are documented in this file.
The format follows Keep a Changelog. This project adheres to Semantic Versioning.
2.0.0 - 2026-08-13
Single-Process In-Process Architecture, Pydantic Hard Dependency, Deterministic Verdict Oracle, and Strict Static Typing.
Breaking Changes
- Elimination of
rootdDaemon: Removed socket daemongui/rootd.py,gui/api/rootd_client.py, andgui/api/deps.py. FastAPI web application andNetnsControllernow run directly in-process with root privileges. - Mandatory Pydantic Dependency:
pydanticpromoted to a mandatory core dependency ofnse/; eliminated all stdlib fallback dataclasses and stubs. - Consolidated Model Hierarchy: Deleted
nse/models/base.py.TopologyTypeandPacketSpecnow collapse to a single source of truth innse.models.test_request. - Target Orchestrator Signature: Rewrote
run_test_pipelinesignature to target standard request-driven API returninglist[TraceEvent]. - Purged Controller State: Removed
enqueue_test,release_test,has_test,get_status,get_event_queue, and_teststracking methods fromNetnsController.
Added
- Trace Harvester Readiness Probe: Added
wait_ready()inTraceHarvesterusingasyncio.Eventreadiness signal, eliminating hardcoded warm-up delay sleeps. - Uniform Naming & Startup Sweep: Created
nse.core.naminghelper withderive_names()and automated orphan netns/veth startup sweep inNetnsController. - Teardown Retry & Subprocess Timeouts: Implemented retry backoff in
destroy_netnsand enforcedtimeout=parameters across allsubprocess.runcalls. - Strict Static Typing & Import Boundaries: Enforced
mypy --strictacross all 22 source files and configuredimport-lintercontract preventingnse/from importinggui/. - MkDocs Web Documentation: Created comprehensive web documentation site powered by MkDocs Material and
mkdocstrings. - Local CI Automation: Added
make ci-localandmake docsMakefile targets.
1.1.1 - 2026-08-05
Kernel tracing initialization fix, background noise filtering in YAML test runner, and Makefile dynamic binary resolution.
Added
- Automatic Kernel Tracing Prepending: Automatically inject a high-priority
table inet nse_traceprerouting chain (meta nftrace set 1) inRuleEngine.load()to guaranteenft monitor tracecaptures trace events for all test packets.
Fixed
- YAML Runner Trace Noise Filtering: Filtered out background setup noise (IPv6 NDP, DAD, MLD, and socket init packets) in
nse.cli.runnerto accurately match verdicts (ACCEPT/DROP) to injected test packets. nft monitor traceRegex Parser: Updated_PACKET_REingui/daemon/trace_harvester.pyto handle both quoted and unquotediifstrings in trace lines across different Linux kernel andnftablesversions.- Dynamic Executable Resolution in Makefile: Updated
Makefileto dynamically detectPYTHON,RUFF,TWINE, andPYTESTin.venvwith automatic fallbacks toPATHsystem binaries. - Ruff Code Quality Compliance: Resolved all Ruff static analysis errors (
ASYNC221,I001,BLE001,UP037,TRY401,PIE790) acrossnse/,gui/, andtests/.
1.1.0 - 2026-06-19
Introducing native container environments support and a Zero-Trust Privilege Separation architecture for the web server.
Added
- Native Container Support (
nsenterfallback): Added robust container detection innse/core/utils.py(checkingcontainerenv,/.dockerenv,/proc/1/environ, andcgroupformat). Dynamic fallback fromip netns exectonsenter --netnamespace switching prevents remount errors in container runtimes. - Zero-Trust Privilege Separation:
nse-rootdUNIX domain socket server running as root and managing network namespaces, Scapy injection, and trace harvesting. Secure/var/run/nse-core.socksocket is automatically chowned toSUDO_UID/SUDO_GIDwhen run viasudo.RootdClientclient proxy allowing unprivileged web server instances (nse-web/gui/server.py) to delegate low-level sandbox execution without running as root.- Dedicated RPC Unit Tests: Added asynchronous mocking test
test_rootd_rpc_communicationto verify JSON-RPC protocol between client and daemon.
Changed
- Makefile and dev-setup: Restructured commands (
make run-rootd,make run-web,make backend, andmake dev) and updated startup instructions to reflect the decoupled daemon architecture.
1.0.0 - 2026-06-18
First stable release of the Network Sandbox Engine.
Summary
NSE v1.0.0 is published as a headless Python library (network-sandbox-engine on PyPI) with an optional GUI layer that lives in-repository. The core engine depends only on scapy; CLI tooling requires pydantic and pyyaml via the [cli] extra. The GUI daemon (FastAPI and Svelte) is excluded from the wheel by design and is run from a repository clone.
Added
Core Headless Engine (nse/)
NetnsController: async context manager for ephemeral Linux network namespace lifecycle (create, configure, teardown). Supportssimple(host to sandbox) andgateway(host to router to server) topologies.PCAPAsserter: wraps ScapyAsyncSnifferto arm BPF-filtered captures on veth interfaces and assert captured packet counts in integration tests.RuleEngine: validates and loadsnftablesrulesets usingnft --check -fandnft -f. Parses line-level error messages into structuredRuleValidationErrorexceptions. Automatically arms kernel tracing viameta nftrace set 1.ScapyInjector: forges and injects IPv4/IPv6 TCP, UDP, ICMP, and ICMPv6 packets at Layer 2/3. Uses in-processsendp()for host-originating packets andip netns execsubprocess for egress from inside a namespace.run_test_pipeline(): top-level orchestrator that chains validation, topology setup, mock listener spawning, rule loading, trace harvesting, sequential packet injection, conntrack polling, and namespace teardown.parse_conntrack_line(): parser for/proc/net/nf_conntrackentries. Extractsproto,state,src,dst,sport, anddportfor both IPv4 and IPv6 flows.- Stateful traffic and conntrack integration:
/proc/net/nf_conntrackis polled after each packet injection and connection states (SYN_SENT,ESTABLISHED,TIME_WAIT) are streamed to consumers. - Dual-stack IPv4/IPv6: all veth links are configured with both address families. DAD is disabled globally inside namespaces (
accept_dad=0) for instant address availability.
Data Models (nse/models/)
PacketSpec: Pydantic model (lazy import) defining protocol, IPs, ports, TCP flags, and packet size. Validates IPv4/IPv6 addresses and allowed flag values.TestRequest: Pydantic model withrules,packets: list[PacketSpec], andtopology: TopologyType.TopologyType: string enum with valuessimpleandgateway.TraceEvent: Pydantic model for kernel trace output events of typehook,match, orverdict.base.py: pure stdlib dataclasses for use without Pydantic.
CLI Runner (nse/cli/runner.py)
nse-runner --file <yaml>CLI entrypoint registered inpyproject.toml.- Reads YAML test suites, invokes
run_test_pipeline(), evaluates expected verdicts, and prints formatted results. - Silent drops (no matching
TraceEvent) are treated asDROP. - Exits with
0on full pass,1on any failure. - Displays a clear install hint if
pydanticorpyyamlis missing.
GUI Daemon (gui/ - not on PyPI)
TraceHarvester: async subprocess spawningnft monitor traceinside the evaluation namespace. Parsed events are pushed into anasyncio.Queue.MockListener: background TCP/UDP echo daemon spawner usingip netns exec. Enables complete TCP handshakes and valid conntrack state generation.- FastAPI REST API:
POST /api/testandGET /api/status/{test_id}. - WebSocket streaming:
WS /ws/{test_id}streamsTraceEventJSON messages to the frontend.
Frontend (gui/gui_svelte/ - not on PyPI)
- Rule editor for
nftablesruleset authoring. - Multi-packet sequence crafter with topology selector.
- Real-time animated pipeline visualizer: hook, rule match, and verdict events.
- Conntrack table: live tabular view of active connection states.
- Offline documentation view at
#/docs.
Packaging and Release
pyproject.tomlat repository root. Build backend:setuptools. Targets onlynse/viapackages.find.include. Hard dependency:scapy>=2.5.0. Optional extra[cli]:pydantic>=2.0.0andpyyaml>=6.0.make release: runslint + test, builds the wheel and source distribution, copies deployment assets, generatesSHA256SUMS, and signs it with GPG. The signing key is auto-detected from the keyring and can be overridden withGPG_KEY_ID=<id>.Dockerfile: multi-stage production image for containerized daemon deployment.scripts/nse.service: systemd unit template binding to/run/nse.sockin production.tests/test_netns.py: unified test suite with 20 unit tests and 2 root-only integration tests.conftest.py: rootsys.pathinjection allowing pytest to discover bothnse/andgui/packages.
Makefile Targets
| Target | Description |
|---|---|
make setup |
Bootstrap venv and run npm install |
make test |
Run unit tests |
make integration-test |
Run root-level integration tests |
make lint |
Ruff static analysis |
make format |
Ruff auto-format |
make verify |
Run lint and test |
make release |
Build and sign all release artifacts |
make publish-test |
Upload to TestPyPI via Twine |
make publish |
Upload to PyPI via Twine |
Changed
- Repository restructured from a monolithic
backend/nse/layout to a root-level separation: nse/is the headless PyPI package (replacesbackend/nse/).gui/is the GUI daemon (replaces GUI modules formerly inbackend/nse/and thefrontend/directory).tests/is the unified test suite (replacesbackend/tests/).TraceHarvesterandMockListenermoved togui/daemon/. These components are part of the GUI layer and are not included in the wheel.- Pydantic imports in
nse/models are wrapped intry/except ImportErrorto allow the core to be imported with onlyscapyinstalled. TestRequest.packetchanged toTestRequest.packets: list[PacketSpec]to support packet sequences. This is a breaking API change.pyproject.tomlmigrated frombackend/pyproject.tomlto the repository root. Build backend changed from Poetry to setuptools.Makefileupdated with root-level paths.
Fixed
- GPG signing in
make releasefailed with "no default secret key" in non-interactive shells. Fixed by adding--local-user $(GPG_KEY_ID)with automatic key detection from the keyring. - Interface name assertion in
test_create_namespace_lifecycle_mockedwas off by one character for 8-character namespace names. - Svelte compilation crash caused by raw curly braces in code blocks. Fixed by escaping them as
{and}.