-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Django autoescape should be enable by default #326
Conversation
@gaby |
@ReneWerner87 I'm not sure yet, the output is now escaped which broke all the unit tests.
|
Should we provide this feature as a config setting ? (otherwise its a breaking change i guess) |
I do agree |
Ok, Will do that instead. |
Looks like the issue is related to func Test_XSS(t *testing.T) {
engine := New("./views", ".django")
require.NoError(t, engine.Load())
var buf bytes.Buffer
err := engine.Render(&buf, "simple", map[string]interface{}{
"Title": "<script>alert('XSS')</script>",
})
require.NoError(t, err)
expect := `<h1><script>alert('XSS')</script></h1>`
result := trim(buf.String())
require.Equal(t, expect, result)
} but this does not: func Test_XSS(t *testing.T) {
engine := New("./views", ".django")
require.NoError(t, engine.Load())
var buf bytes.Buffer
err := engine.Render(&buf, "index", map[string]interface{}{
"Title": "<script>alert('XSS')</script>",
}, "layouts/main")
require.NoError(t, err)
expect := `<!DOCTYPE html><html><head><title>Main</title></head><body><h2>Header</h2><h1><script>alert('XSS')</script></h1><h2>Footer</h2></body></html>`
result := trim(buf.String())
require.Equal(t, expect, result)
} |
Confirm, it has to do with <!DOCTYPE html>
<html>
<head>
<title>Main</title>
</head>
<body>
{{embed | safe}}
</body>
</html> |
The fiber/django template uses its own non-standard I believe that the appropriate way to do this in Django would be to use the following template code: {% extends "layouts/main.django" %}
{% block content %}
{% include "partials/header.django" %}
<h1>{{ Title }}</h1>
{% include "partials/footer.django" %}
{% endblock %} and then this in the parent (layout): <!DOCTYPE html>
<html>
<head>
<title>Main</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html> With that this would be the test: func Test_XSS(t *testing.T) {
engine := New("./views", ".django")
require.NoError(t, engine.Load())
var buf bytes.Buffer
err := engine.Render(&buf, "index", map[string]interface{}{
"Title": "<script>alert('XSS')</script>",
})
require.NoError(t, err)
expect := `<!DOCTYPE html><html><head><title>Main</title></head><body><h2>Header</h2><h1><script>alert('XSS')</script></h1><h2>Footer</h2></body></html>`
result := trim(buf.String())
require.Equal(t, expect, result)
} By having a custom fiber way to do the same with |
@gaby a non-breaking change (eg. we still support // Wrokaround for custom {{embed}} tag
// Mark the `embed` variable as safe
// it has already been escaped above
// e.LayoutName will be 'embed'
safeEmbed := pongo2.AsSafeValue(parsed)
// Add the safe value to the binding map
bind[e.LayoutName] = safeEmbed Then we can keep also recommend adding this test: func Test_XSS(t *testing.T) {
engine := New("./views", ".django")
require.NoError(t, engine.Load())
var buf bytes.Buffer
err := engine.Render(&buf, "index", map[string]interface{}{
"Title": "<script>alert('XSS')</script>",
}, "layouts/main")
require.NoError(t, err)
expect := `<!DOCTYPE html><html><head><title>Main</title></head><body><h2>Header</h2><h1><script>alert('XSS')</script></h1><h2>Footer</h2></body></html>`
result := trim(buf.String())
require.Equal(t, expect, result)
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add fix on line 235 per my comment above and add XSS test.
@ReneWerner87 I think we should issue a CVE and GitHub security advisory for this too. |
I'm not sure how to add a config variable for template engines, they are different than contrib/storage middlewares. Although I think we should just enable this by default to avoid issues in the future. The changes don't break existing functionality. |
Ping @ReneWerner87 @efectn |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While approving, we should review removing custom layout handling like {{embed}}
and more directly supporting Django templates and their approach. Ref: #327
I believe it's not a good idea to turn off AutoEscape globally. It can lead to serious issues and should be avoided. Template authors can turn it off per block: {% autoescape off %}
{{ "<script>alert('xss');</script>" }}
{% endautoescape %} https://github.com/flosch/pongo2/blob/master/template_tests/autoescape.tpl or per var: <h1>{{ someSafeVar | safe }}</h1>
{{ "<script>"|safe }} https://github.com/flosch/pongo2/blob/master/template_tests/filters.tpl |
@gaby // Create a new engine
engine := django.New("./views", ".django")
engine.SetAutoEscape(true) @gaby @sixcolors could we add a part about escaping or security in the readme as a section for this -> best practices
@sixcolors yes i also think that fenny wanted a common way that works for everyone and therefore added the custom
as long as it has no negative consequences, we could also activate it by default so either add a specific config setting in this engine where you can control AutoEscape via setter, or as config property in another argument to the NEW functions |
spelling fix
@ReneWerner87 I like this approach you suggested: // Create a new engine
engine := django.New("./views", ".django")
engine.SetAutoEscape(true) I will update that today and also add a note on the README. |
Shouldn't the default setting be secure, eg the zero value would be the secure option? |
Yes, just an example. |
@sixcolors @ReneWerner87 @efectn Added support for making autoescape configurable, update docs, and added unit-tests for XSS. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a note about using per variable | safe or turning auto escape off in blocks of template code?
Done, thanks for the suggestion. |
@ReneWerner87 @efectn Updated based on last comments, should be good to merge. |
The
pongo2
library by default hasautoescape
set toTrue
as seen here: https://github.com/flosch/pongo2/blob/master/context.go#L11 . We should do the same as this exposes the user to XSS.Fixes #281