Skip to content

Restrict Jinja environment_params path imports to an allowlist (CVE-2026-29514)#22078

Closed
Chocapikk wants to merge 1 commit into
netbox-community:mainfrom
Chocapikk:fix/jinja-finalize-allowlist
Closed

Restrict Jinja environment_params path imports to an allowlist (CVE-2026-29514)#22078
Chocapikk wants to merge 1 commit into
netbox-community:mainfrom
Chocapikk:fix/jinja-finalize-allowlist

Conversation

@Chocapikk

Copy link
Copy Markdown

Fix: restrict Jinja environment_params path imports to an allowlist (CVE-2026-29514)

What this fixes

RenderTemplateMixin.get_environment_params() resolves the undefined and finalize keys via Django's import_string() with no restriction. Any authenticated user with extras.add_exporttemplate (or extras.add_configtemplate + extras.render_configtemplate) can pass finalize: "subprocess.getoutput" and execute arbitrary shell commands as the NetBox service user when the template is rendered.

Tracked as CVE-2026-29514 (CVSS 8.8 High, CWE-94).

Where the bug came from

The path-import behavior was introduced in 063d1fe (#19962, "Closes #18797: Support path import for certain Jinja environment parameters", 2025-07-29) and has been unchanged since. v4.5.4 and current main are byte-identical for netbox/extras/models/mixins.py.

Fix

  • New constant JINJA_ENV_PARAM_IMPORT_ALLOWLIST in extras/constants.py mapping each path-import key to the set of dotted paths that may be resolved:
    • undefined: the four Jinja2 undefined classes (Undefined, ChainableUndefined, DebugUndefined, StrictUndefined).
    • finalize: empty by default. No arbitrary callable can be imported.
  • RenderTemplateMixin.clean() now rejects unsafe values at save time.
  • RenderTemplateMixin.get_environment_params() re-validates at render time (defense in depth) and works on a copy of environment_params so the stored value is never mutated.

Tests

extras.tests.test_models.JinjaEnvironmentParamsTest covers:

  • allowlisted undefined value resolves correctly,
  • disallowed undefined value is rejected,
  • the original finalize: subprocess.getoutput payload is rejected at clean(),
  • get_environment_params() rejects unsafe values even when clean() was bypassed,
  • non-path-import parameters (trim_blocks, lstrip_blocks) are unaffected.

References

…026-29514)

RenderTemplateMixin.get_environment_params() resolved any dotted path passed
in environment_params['undefined'] or environment_params['finalize'] via
import_string(). Any authenticated user with extras.add_exporttemplate (or
extras.add_configtemplate + extras.render_configtemplate) could pass
'finalize: subprocess.getoutput' and execute arbitrary shell commands as the
NetBox service user when the template was rendered.

Tracked as CVE-2026-29514 (CVSS 8.8 High, CWE-94).

The path-import behavior was introduced in 063d1fe (PR netbox-community#19962) on
2025-07-29 and has been unchanged since.

Fix:
- Add JINJA_ENV_PARAM_IMPORT_ALLOWLIST in extras/constants.py listing
  the dotted paths that may be resolved for each path-import key.
  - 'undefined': the four jinja2 undefined classes only.
  - 'finalize': empty by default, no arbitrary callable can be imported.
- RenderTemplateMixin.clean() rejects unsafe values at save time.
- RenderTemplateMixin.get_environment_params() re-validates at render
  time (defense in depth) and works on a copy of environment_params so
  the stored value is never mutated.

Tests cover the allowlisted path resolving, the disallowed values being
rejected at clean() and at render time, and unrelated parameters
(trim_blocks, lstrip_blocks) being unaffected.

Signed-off-by: Chocapikk <balgogan@protonmail.com>
@jeremystretch

Copy link
Copy Markdown
Member

Thank you for your interest in contributing to NetBox, however it appears there is no accepted issue that correlates to this pull request. Before pull requests are opened, we require an accepted issue as per our contributing guide. Please first open an issue and wait for it to be accepted before further work is done on this pull request.

@Chocapikk

Copy link
Copy Markdown
Author

Hi @jeremystretch,

Apologies for skipping that step. Context: this is a security fix (CVE-2026-29514) originally reported to security@netboxlabs.com on 2026-03-10. With no maintainer response, the CNA (VulnCheck) suggested either opening a public issue or going straight to a PR to make sure something land before the patch window expired - the path-import behavior introduced in 063d1fe has been exploitable since then.

I just opened an issue: #22079

Happy to wait for it to be triaged before any further work on this PR. Let me know if you'd like me to adjust anything.

Thanks for the quick review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Config Template Rendering: Option for jinja2.StrictUndefined

2 participants