Opened 5 years ago

Closed 5 years ago

#31287 closed Cleanup/optimization (wontfix)

Rename mark_safe and "safe" template filters to something less safe sounding

Reported by: Adam Johnson Owned by: nobody
Component: Template system Version: dev
Severity: Normal Keywords:
Cc: Josh Smeaton Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

As discussed on django-developers in Jan 2018: https://groups.google.com/forum/#!msg/django-developers/AvgxWR-0VrE/b8a3g8q-AwAJ . And occasionally brought up again in other community forums, many developers reporting overuse of mark_safe() in real world projects.

Copying Stuart Cox's first post from the mailing list thread:

In my experience, misuse of mark_safe() — i.e. marking stuff safe which isn’t actually safe (e.g. HTML from a rich text input) — is one of the biggest causes of XSS vulnerabilities in Django projects.

The docs warn to be careful, but unfortunately I think Django devs have just got too used to mark_safe() being the way to insert HTML in a template. And it’s easy for something that was safe when it was authored (e.g. calling mark_safe() on a hard-coded string) to be copied / repurposed / adapted into a case which is no longer be safe (e.g. that string replaced with a user-provided value).

Some other frameworks use scary sounding names to help reinforce that there are dangers around similar features, and that this isn’t something you should use in everyday work — e.g. React’s dangerouslySetInnerHTML.

Relatedly, this topic suggested making it more explicit that mark_safe() refers to being safe for use in HTML contexts (rather than JS, CSS, SQL, etc).

Combining the two, it would be great if Django could rename mark_safe() to dangerously_trust_html(), |safe to |dangerously_trust_html, @csrf_exempt to @dangerously_csrf_exempt, etc.

Developers who know what they’re doing with these could then be encouraged to create suitable wrappers which handle their use case safely internally — e.g.:

@register.filter
def sanitize_and_trust_html(value):
    # Safe because we sanitize before trusting
   return dangerously_trust_html(bleach.clean(value))

Change History (2)

comment:1 by Claude Paroz, 5 years ago

Meh... You will annoy thousands of devs having to rename multiple occurrences of those names, with IMHO a very small gain. EIther the developer is sensible to security coding and she's probably already careful about those, or the developer doesn't care and just wants to see its string be shown properly, whatever the name of the function is.
TL;DR I'm not convinced.

comment:2 by Carlton Gibson, 5 years ago

Resolution: wontfix
Status: newclosed

Yeah, look... I see it... But without a consensus for the change on the mailing list I don't see grounds for a ticket. The case needs to be made there.
Pending something like that, I don't feel we can just bypass the list and Accept a ticket here.
I hope that makes sense.

Note: See TracTickets for help on using tickets.
Back to Top