#34581: Filters should not implicitly mark unsafe strings as safe without 
escaping
------------------------------------------------+------------------------
               Reporter:  Shai Berger           |          Owner:  nobody
                   Type:  Cleanup/optimization  |         Status:  new
              Component:  Template system       |        Version:  dev
               Severity:  Normal                |       Keywords:
           Triage Stage:  Unreviewed            |      Has patch:  0
    Needs documentation:  0                     |    Needs tests:  0
Patch needs improvement:  0                     |  Easy pickings:  0
                  UI/UX:  0                     |
------------------------------------------------+------------------------
 Consider the following template code snippet:
 {{{
 {% autoescape off %}
 {{ some_list|join:some_var }}
 {% endautoescape %}
 }}}
 As noted in #34574, the current implementation joins the members of
 {{{some_list}}} without escaping them, but marks the end result as safe
 (since #34578, the joiner {{{some_var}}} is not escaped either -- but in
 most common use, it is a literal in the template, so it is safe to begin
 with).

 Given that we already have a {{{safeseq}}} filter, and #34577 is
 introducing {{{escapeseq}}} as well, I think we should change the behavior
 of {{{join}}} and other related filters (an initial list that was given in
 the related discussion in the security team includes {{{linenumbers}}},
 {{{linebreaks}}}, and {{{linebreaksbr}}}, but there are probably others)
 so they don't mark unsafe strings as safe without escaping them.

 The details change by the specific filter: The {{{join}}} filter may
 output an unsafe string when all of its inputs are unsafe. The
 {{{linebreaks}}} filter cannot -- it introduces HTML tags into its output,
 so this output must be marked safe. The {{{join}}} filter, too, should
 preserve safety -- so if some input (in the sequence or the joiner) is
 safe, again, the output must be safe.

 When a filter gets an unsafe input, must produce a safe output, and
 autoescape is on, there's no real problem -- the input can be escaped.
 This is current behavior, mostly ({{{join}}} escapes input and marks the
 output safe, even if it isn't forced to).

 But when autoescaping is off, inputs are not escaped -- however, the
 output, which usually includes their content verbatim, is still marked
 safe.

 I suggest a general rule: A filter which gets unsafe input, should not
 escape it, and yet needs to produce safe output, should error out. This is
 a hardening, not a security fix, so it should follow a normal deprecation
 cycle: The actual change should only happen after the next LTS release.

 This would affect many filters, and is backwards-incompatible, but I think
 it would make the escaping more consistent and predictable, and it would
 make Django more safe-by-default for some less-common use-cases.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34581>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/01070188389efdda-9bfdb04c-9a14-45f5-b874-6fd1b26f65e4-000000%40eu-central-1.amazonses.com.

Reply via email to