Skip to content
Permalink
Browse files Browse the repository at this point in the history
Enforce sandboxed rendering for Jinja2 templates.
- This forces the Jinja2 template renderer to use a `SandboxedEnvironment`
- This addresses any unsafe code execution everywhere `render_jinja2` is called.
- Test added to assert that unsafe attributes cannot be accessed and will result in a `SecurityError`.
- Documentation referencing direct use of `jinja2.Template` replaced with `render_jinja2`
  • Loading branch information
jathanism committed Jan 4, 2023
1 parent 10a092b commit d47f157
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 6 deletions.
1 change: 1 addition & 0 deletions nautobot/core/settings.py
Expand Up @@ -468,6 +468,7 @@
"nautobot.core.context_processors.settings",
"nautobot.core.context_processors.sso_auth",
],
"environment": "jinja2.sandbox.SandboxedEnvironment",
},
},
]
Expand Down
8 changes: 4 additions & 4 deletions nautobot/docs/models/dcim/deviceredundancygroup.md
Expand Up @@ -142,7 +142,7 @@ The following snippet represents an example Cisco ASA failover configuration tem

```python
# Configuration Template for Cisco ASA
template_body="""
template_code = """
{% set redundancy_members = gql_data['data']['devices'][0]['device_redundancy_group']['members'] %}
{% set failover_device_local = redundancy_members[0] if redundancy_members[0].name == device else redundancy_members[1] %}
{% set failover_device_peer = redundancy_members[0] if redundancy_members[0].name != device else redundancy_members[1] %}
Expand Down Expand Up @@ -172,15 +172,15 @@ failover
Following snippet represents an example Cisco ASA Failover rendered configuration:

```python
from jinja2 import Template
from nautobot.utilities.utils import render_jinja2
tm=Template(template_body)
nyc_fw_primary_config = tm.render(
context = dict(
device=hostname,
gql_data=gql_data,
priority_mapping={50: 'secondary', 100: 'primary'}
)
nyc_fw_primary_config = render_jinja2(template_code=template_code, context=context)
print(nyc_fw_primary_config)
```
Expand Down
21 changes: 19 additions & 2 deletions nautobot/utilities/tests/test_jinja_filters.py
@@ -1,9 +1,9 @@
from django.test import TestCase
from jinja2.exceptions import TemplateAssertionError

from jinja2.exceptions import SecurityError, TemplateAssertionError
from netutils.utils import jinja2_convenience_function

from nautobot.utilities.utils import render_jinja2
from nautobot.dcim.models import Site


class NautobotJinjaFilterTest(TestCase):
Expand Down Expand Up @@ -64,3 +64,20 @@ def test_netutils_filters_in_jinja(self):
raise
except Exception:
pass

def test_sandboxed_render(self):
"""Assert that Jinja template rendering is sandboxed."""
template_code = "{{ ''.__class__.__name__ }}"
with self.assertRaises(SecurityError):
render_jinja2(template_code=template_code, context={})

def test_safe_render(self):
"""Assert that safe Jinja rendering still works."""
site = Site.objects.filter(region__isnull=False).first()
template_code = "{{ obj.region.name }}"
try:
value = render_jinja2(template_code=template_code, context={"obj": site})
except SecurityError:
self.fail("SecurityError raised on safe Jinja template render")
else:
self.assertEqual(value, site.region.name)

0 comments on commit d47f157

Please sign in to comment.