Introduction
An authenticated user with nothing more than template creation permissions in NetBox can achieve full remote code execution on the underlying server, bypassing Jinja2's sandbox protections through a subtle but powerful mechanism in the template rendering pipeline. For organizations relying on NetBox to manage their network infrastructure data, this vulnerability (CVE-2026-29514, CVSS 8.8) exposes not just the application itself but the database credentials, Redis secrets, and complete network topology stored within it.
NetBox is an open source infrastructure resource modeling application widely used across enterprise and service provider environments to document and manage IP address allocations, rack layouts, device inventories, and cabling. Originally developed by DigitalOcean and now maintained by NetBox Labs and the community, it serves as a foundational source of truth for network automation workflows. Its role as a central repository for sensitive infrastructure metadata makes any code execution vulnerability in NetBox particularly consequential.
Technical Information
The root cause of CVE-2026-29514 lies in how NetBox's RenderTemplateMixin.get_environment_params() method handles the finalize and undefined parameters that are passed to the Jinja2 SandboxedEnvironment. The method uses Django's import_string() function to resolve these parameters into Python callables at runtime, but it does so without any allowlist or validation of the import path.
Jinja2's SandboxedEnvironment is designed to restrict what template code can do by intercepting dangerous function calls within the template evaluation sandbox. However, the finalize parameter occupies a special position in Jinja2's architecture: it is a callable that is invoked on every rendered expression as a post processing step, and critically, this invocation happens outside the sandbox's call interception mechanism. This means that even though the sandbox would normally block calls to dangerous functions like subprocess.getoutput, setting that function as the finalize callable sidesteps the protection entirely.
Attack Flow
The exploitation path is straightforward:
- An attacker authenticates to NetBox with an account that holds template creation permissions (either
extras.add_exporttemplateorextras.add_configtemplate). - The attacker creates a new template object, setting the
finalizefield withinenvironment_paramstosubprocess.getoutput. - The template body contains a simple string literal that doubles as a shell command, such as
{{ "id" }}. - The attacker triggers template rendering.
- During rendering, Jinja2 evaluates the expression
"id"(a plain string), then passes it to thefinalizecallable, which is nowsubprocess.getoutput. - The string
"id"is executed as a shell command, and the output is returned directly in the HTTP response body.
Two Attack Vectors
Due to model inheritance in NetBox's template system, there are two distinct paths to exploitation:
| Attack Vector | Required Permissions | Trigger Method |
|---|---|---|
| ExportTemplate | extras.add_exporttemplate and extras.view_exporttemplate | GET request to list endpoints with export parameter |
| ConfigTemplate | extras.add_configtemplate and extras.render_configtemplate | POST request to render endpoint |
Execution Context
In Docker deployments, the NetBox service runs as uid=999 (netbox) with gid=0 (root). Successful exploitation grants the attacker command execution in a context that has access to database credentials, Redis credentials, and the full network topology data stored in NetBox. The direct command output in the HTTP response body makes this a particularly clean and reliable exploitation path, requiring no out of band data exfiltration channels.
Why the Sandbox Fails
The key insight is architectural. Jinja2's SandboxedEnvironment intercepts calls made within template expressions, such as {{ foo.bar() }}. But the finalize function is part of the environment's own rendering machinery. It is called by the engine itself on the result of every expression, not by the template code. The sandbox has no mechanism to evaluate whether the finalize callable is safe because it was never designed to guard against a malicious environment configuration. The vulnerability is therefore not a flaw in Jinja2 itself, but in NetBox's decision to allow user controlled input to configure the Jinja2 environment without restriction.
It is worth noting that during the original code review in July 2025 when this feature was introduced, a reviewer explicitly asked about validation of the import paths. The code was merged without an allowlist, leaving the door open for this bypass.
Affected Systems and Versions
The vulnerability affects NetBox versions 4.3.5 through 4.5.4 inclusive. Any deployment within this version range where non staff users hold template creation or rendering permissions is vulnerable.
Both the ExportTemplate and ConfigTemplate models are affected. Docker based deployments carry additional risk due to the service running with gid=0 (root group).
Vendor Security History
The disclosure timeline for this vulnerability highlights some process concerns. Coordinated disclosure emails were sent to the NetBox security contact address on March 10, 2026, but these emails were reportedly lost. This communication failure forced the security researcher to open a public tracking issue on May 4, 2026, effectively converting a private disclosure into a public one. Combined with the July 2025 code review where validation was discussed but not implemented, this suggests that both the development review process and the vulnerability intake pipeline have room for improvement.
References
- NVD Entry for CVE-2026-29514
- CVE-2026-29514: NetBox Jinja2 Sandbox Bypass to RCE via RenderTemplateMixin environment_params (Chocapikk)
- NetBox GitHub Issue #22079: Public Tracking Issue
- NetBox Pull Request #22078: Restrict Jinja environment_params path imports to an allowlist
- VulnCheck Advisory: NetBox RCE via RenderTemplateMixin
- GitHub Advisory Database: GHSA-f249-4qx6-hg68



