#14976: Add is_html flag to contrib.messages
-----------------------------------+----------------------------------------
Reporter: tedtieken | Owner: nobody
Status: new | Milestone:
Component: Contrib apps | Version: 1.2
Resolution: | Keywords: safe, messages, html
Stage: Accepted | Has_patch: 0
Needs_docs: 0 | Needs_tests: 0
Needs_better_patch: 0 |
-----------------------------------+----------------------------------------
Changes (by tedtieken):
* keywords: safe, messages => safe, messages, html
Comment:
Not sure where "test" came from... probably end of the day brain fog.
Agree with the change to "is_html"
'''Cookie backend.''' [[BR]]
The current method stores the message as a 3 or 4 item list in json:
[flag, level, message, ''optionally extra_tags'']. The decoding method
relies on this information being a list of 3 or 4 items to recreate the
message object:
{{{
#obj is the json object transformed into a list, obj[0] is a flag set to
'__json_message'
return Message(*obj[1:])
}}}
Adding another optional argument creates a problem. If we have [flag,
level, message, extra_tags, is_html] the message decoding works, but if we
have [flag, level, message, is_html] then the is_html tag is positionally
interpreted as the value of extra_tags.
The solution I see to this is always store ''extra_tags'' and optionally
store ''is_html.'' In the case where there aren't extra tags, store an
empty string.
{{{
class MessageEncoder(json.JSONEncoder):
"""
Compactly serializes instances of the ``Message`` class as JSON.
"""
message_key = '__json_message'
def default(self, obj):
if isinstance(obj, Message):
message = [self.message_key, obj.level, obj.message]
if obj.extra_tags:
message.append(obj.extra_tags)
else: #New
message.append(str()) #New
if obj.is_html: #New
message.append(obj.is_html) #New
return message
return super(MessageEncoder, self).default(obj)
}}}
In the no extra_tags scenario, this solution has additional storage
overhead of 4 characters - ,"", - IMHO that's acceptable.
Legacy cookies will continue to pass the hash check because we haven't
changed the hashing algorithm or what was stored.
Since legacy messages are lists of length 3 or 4 and will never have the
is_html flag set to true, the Message() call would still behave as
expected with legacy cookies - the call would be either Message(level,
message) or Message(level, message, extra_tags).
'''XSS'''
To use cookie stored messages in an xss attack, the attacker would have to
know the site's secret key, because if the hash doesn't match the cookie
backend discards the messages.
Putting user input into an un-escaped output always has the possibility to
open up an xss hole, but no more here than in any other feature. By
having is_html as an optional, False-by-default variable I think we make
it pretty hard to accidentally display a message as html.
Going to take a look at the session backend tonight.
--
Ticket URL: <http://code.djangoproject.com/ticket/14976#comment:3>
Django <http://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 post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.