From ca7caecac5a0ad4fc8cd3601b7439136bbb52fad Mon Sep 17 00:00:00 2001 From: bctiemann Date: Sat, 11 Jul 2026 12:37:52 -0400 Subject: [PATCH] Closes #22652: Disable autoescaping for Config Templates (#22653) Force autoescape=False in ConfigTemplate.get_environment_params() after merging user-supplied environment parameters. Config templates produce plain-text network configurations and scripts, so HTML autoescaping is not applicable. Keep the override out of the shared render_jinja2() helper so export templates can continue to use autoescape=True for HTML output. Add regression coverage for both behaviors. --- netbox/extras/models/configs.py | 10 ++++++++++ netbox/extras/tests/test_models.py | 27 ++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/netbox/extras/models/configs.py b/netbox/extras/models/configs.py index 235cf7160..f8e906663 100644 --- a/netbox/extras/models/configs.py +++ b/netbox/extras/models/configs.py @@ -316,6 +316,16 @@ class ConfigTemplate( self.template_code = self.data_file.data_as_string sync_data.alters_data = True + def get_environment_params(self): + """ + Config templates render plain text (network configs, scripts), not HTML. Force + autoescape off so environment_params cannot enable it and create a latent XSS sink + if output is ever rendered in an HTML context. + """ + params = super().get_environment_params() + params['autoescape'] = False + return params + def format_render_error(self, exc): """ Return a formatted error string for a rendering exception. When debug is enabled, the full diff --git a/netbox/extras/tests/test_models.py b/netbox/extras/tests/test_models.py index e55304cbd..ce7940a93 100644 --- a/netbox/extras/tests/test_models.py +++ b/netbox/extras/tests/test_models.py @@ -1310,6 +1310,24 @@ class RenderTemplateMixinRenderTestCase(TestCase): self.assertNotEqual(plain.render(ctx), trimmed.render(ctx)) self.assertEqual(trimmed.render(ctx).strip(), 'VALUE') + def test_configtemplate_autoescape_always_disabled(self): + """ + ConfigTemplate renders plain text (network configs, scripts); autoescape must stay off + even if environment_params explicitly requests it (#22652). + """ + t = ConfigTemplate(name='autoescape', template_code='{{ value }}', environment_params={'autoescape': True}) + self.assertEqual(t.render({'value': '