Admin: sandbox jinja2 templates in emails#4106
Conversation
mathjazz
left a comment
There was a problem hiding this comment.
I'm afraid this is not the right fix for #3985, which sadly has a misleading title.
The sandbox reduces risk but doesn't eliminate it, and it does so at the cost of ongoing complexity and trust in a security boundary that has already failed before. Eliminating the execution model entirely is a fundamentally stronger position.
Considering we still want editors to write template-like content in the DB, we should use a logic-less engine that has no concept of code execution.
We should probably be good with using str.format_map():
body = template_str.format_map({
"INACTIVE_CONTRIBUTOR_PERIOD": settings.INACTIVE_CONTRIBUTOR_PERIOD,
"homepage_url": request.build_absolute_uri(reverse("pontoon.homepage")),,
})Alternatively, we could look into something more advanced like Chevron.
|
I see what you mean - we want to eliminate |
|
Yeah. |
Codecov Report❌ Patch coverage is 🚀 New features to boost your workflow:
|
cbfb112 to
8c189d3
Compare
|
Just spent the last couple of hours debugging this - apparently the removal of jinja2 I'm including the test change in this PR as its small and makes more sense to explain it here rather than merge seperately. |
mathjazz
left a comment
There was a problem hiding this comment.
This moves in the right direction by removing Jinja execution for DB email content. 👏
Note that format_map() still allows attribute access and currently receives a Django model instance. Please replace it as suggested.
We should also update the template files accordingly.
First in the repo:
https://github.com/functionzz/pontoon/tree/eb266b7b8a870461e8e7baecdafba7932ce6720a/pontoon/messaging/templates/messaging/emails/content
Then in the DB.
| response = client_superuser.get(url) | ||
| assert response.status_code == 200 | ||
| assert "translate_locale" not in response.context | ||
| assert "Translate" not in response.content.decode() |
There was a problem hiding this comment.
Are these changes related to the PR?
There was a problem hiding this comment.
Yes, but in an indirect way. This test was failing due to reasons I posted about above, I'm including it in this PR so the test passes and there is a paper trail.
There was a problem hiding this comment.
I just tested locally without this change and the tests are passing.
There was a problem hiding this comment.
The remote tests will not pass if the change is not applied. At least that's what I tested recently.
Just quoting myself because I didn't put this comment in the right place - If I push the old code it fails the pytest in CI.
| response = client_superuser.get(url) | ||
| assert response.status_code == 200 | ||
| assert "translate_locale" not in response.context | ||
| assert "Translate" not in response.content.decode() |
There was a problem hiding this comment.
I just tested locally without this change and the tests are passing.
|
The remote tests will not pass if the change is not applied. At least that's what I tested recently. |
Could you please push? I'd like to look into it. |
|
Could you please rebase against upstream/main? |
218740a to
41d9935
Compare
|
Like @mathjazz, this PR passes for me locally without any changes 🤔 |
|
Correction after more ☕ : it fails locally as well, I was only running the emails test, not admin 😳 Looks like the removal of |
|
Forgot to update this yesterday: The PR changes when the default Jinja backend is initialized, which seems to change what Django’s test client captures. so the fix here is to assert rendered behavior instead of Jinja internals. |
5217c5f to
629ca29
Compare
This PR removes the ability for users with admin access to conduct RCE via jinja2 templates within Pontoon onboarding and user inactivity emails. It uses
SandboxedEnvironmentto prevent access to dangerous commands.Fixes #3985.
Note: access to
settingshas been restricted toINACTIVE_CONTRIBUTOR_PERIOD,INACTIVE_TRANSLATOR_PERIODandINACTIVE_MANAGER_PERIOD. Therefore, we must subsequently edit the onboarding and inactivity emails in the PROD and DEV dbs to reflect that, or else we risk crashing Pontoon.Note 2: The above note expanded: all template tags in PROD and DEV must be of the format
{placeholder}.full_urlis no longer used within email templates, and jinja templating brackets ({{}}) are replaced with single brackets ({}).