Commit 0482f8a1 by Jonathan Piacenti

Removed several security features

CMS studio users will be considered trusted from now on. Unfiltered HTML
will be permitted alongside markdown. This does mean that privilege
escalation is easy, as a Javascript snippet could be used to grant
superuser privileges if a superuser visits a page.
parent 59758e5f
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from collections import OrderedDict from collections import OrderedDict
from django.template import Template, Context from django.template import Template, Context
from markdown import markdown
import pkg_resources import pkg_resources
...@@ -10,24 +11,6 @@ from xblock.fields import Scope, String, Dict, List ...@@ -10,24 +11,6 @@ from xblock.fields import Scope, String, Dict, List
from xblock.fragment import Fragment from xblock.fragment import Fragment
from xblockutils.resources import ResourceLoader from xblockutils.resources import ResourceLoader
from .utils import process_markdown
# When changing these constants, check the templates as well for places
# where the user is informed about them.
MAX_PARAGRAPH_LEN = 5000
MAX_URL_LEN = 1000
MAX_ANSWER_LEN = 250
# These two don't have mentions in the templates, but will cause error
# messages.
MAX_ANSWERS = 25
MAX_KEY_LEN = 100
class PollBlock(XBlock): class PollBlock(XBlock):
""" """
...@@ -59,8 +42,8 @@ class PollBlock(XBlock): ...@@ -59,8 +42,8 @@ class PollBlock(XBlock):
def get_results(self, data, suffix=''): def get_results(self, data, suffix=''):
detail, total = self.tally_detail() detail, total = self.tally_detail()
return { return {
'question': process_markdown(self.question), 'tally': detail, 'question': markdown(self.question), 'tally': detail,
'total': total, 'feedback': process_markdown(self.feedback), 'total': total, 'feedback': markdown(self.feedback),
} }
def clean_tally(self): def clean_tally(self):
...@@ -166,9 +149,9 @@ class PollBlock(XBlock): ...@@ -166,9 +149,9 @@ class PollBlock(XBlock):
'choice': choice, 'choice': choice,
# Offset so choices will always be True. # Offset so choices will always be True.
'answers': self.answers, 'answers': self.answers,
'question': process_markdown(self.question), 'question': markdown(self.question),
# Mustache is treating an empty string as true. # Mustache is treating an empty string as true.
'feedback': process_markdown(self.feedback) or False, 'feedback': markdown(self.feedback) or False,
'js_template': js_template, 'js_template': js_template,
'any_img': self.any_image(), 'any_img': self.any_image(),
# The SDK doesn't set url_name. # The SDK doesn't set url_name.
...@@ -213,8 +196,8 @@ class PollBlock(XBlock): ...@@ -213,8 +196,8 @@ class PollBlock(XBlock):
# I wonder if there's something for live validation feedback already. # I wonder if there's something for live validation feedback already.
result = {'success': True, 'errors': []} result = {'success': True, 'errors': []}
question = data.get('question', '').strip()[:MAX_PARAGRAPH_LEN] question = data.get('question', '').strip()
feedback = data.get('feedback', '').strip()[:MAX_PARAGRAPH_LEN] feedback = data.get('feedback', '').strip()
if not question: if not question:
result['errors'].append("You must specify a question.") result['errors'].append("You must specify a question.")
result['success'] = False result['success'] = False
...@@ -229,11 +212,6 @@ class PollBlock(XBlock): ...@@ -229,11 +212,6 @@ class PollBlock(XBlock):
else: else:
source_answers = data['answers'] source_answers = data['answers']
# Set a reasonable limit to the number of answers in a poll.
if len(source_answers) > MAX_ANSWERS:
result['success'] = False
result['errors'].append("")
# Make sure all components are present and clean them. # Make sure all components are present and clean them.
for answer in source_answers: for answer in source_answers:
if not isinstance(answer, dict): if not isinstance(answer, dict):
...@@ -246,11 +224,8 @@ class PollBlock(XBlock): ...@@ -246,11 +224,8 @@ class PollBlock(XBlock):
result['success'] = False result['success'] = False
result['errors'].append( result['errors'].append(
"Answer {0} contains no key.".format(answer)) "Answer {0} contains no key.".format(answer))
if len(key) > MAX_KEY_LEN: img = answer.get('img', '').strip()
result['success'] = False label = answer.get('label', '').strip()
result['errors'].append("Key '{0}' too long.".format(key))
img = answer.get('img', '').strip()[:MAX_URL_LEN]
label = answer.get('label', '').strip()[:MAX_ANSWER_LEN]
if not (img or label): if not (img or label):
result['success'] = False result['success'] = False
result['errors'].append( result['errors'].append(
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
</div> </div>
<span class="tip setting-help"> <span class="tip setting-help">
Enter an answer for the user to select. An answer must have an image URL or text, and can have both. Enter an answer for the user to select. An answer must have an image URL or text, and can have both.
(Text truncated at 250 characters, Image URL at 1000)
</span> </span>
<a href="#" class="button action-button poll-delete-answer" onclick="return false;">Delete</a> <a href="#" class="button action-button poll-delete-answer" onclick="return false;">Delete</a>
</li> </li>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<div id="poll-question-editor-container"> <div id="poll-question-editor-container">
<textarea class="input setting-input" name="question" id="poll-question-editor">{{question}}</textarea> <textarea class="input setting-input" name="question" id="poll-question-editor">{{question}}</textarea>
</div> </div>
<span class="tip setting-help">Enter the prompt for the user. (Truncated after 5000 characters)</span> <span class="tip setting-help">Enter the prompt for the user.</span>
</li> </li>
<li class="field comp-setting-entry is-set"> <li class="field comp-setting-entry is-set">
<h2><label for="poll-feedback-editor">Feedback</label></h2> <h2><label for="poll-feedback-editor">Feedback</label></h2>
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
</div> </div>
<span class="tip setting-help"> <span class="tip setting-help">
This text will be displayed for the user as some extra feedback after they have This text will be displayed for the user as some extra feedback after they have
submitted their response to the poll. (Truncated after 5000 characters) submitted their response to the poll.
</span> </span>
</li> </li>
<li class="field comp-setting-entry is-set"> <li class="field comp-setting-entry is-set">
......
-e . -e .
bleach
markdown markdown
-e git+https://github.com/edx-solutions/xblock-utils.git#egg=xblock-utils -e git+https://github.com/edx-solutions/xblock-utils.git#egg=xblock-utils
from unittest import TestCase from unittest import TestCase
from poll.utils import process_markdown from markdown import markdown
class ProcessMarkdownTest(TestCase): class ProcessMarkdownTest(TestCase):
...@@ -37,6 +37,6 @@ This is a paragraph of text, despite being just one sentence. ...@@ -37,6 +37,6 @@ This is a paragraph of text, despite being just one sentence.
<blockquote> <blockquote>
<p>This is going to be a blockquote.</p> <p>This is going to be a blockquote.</p>
</blockquote> </blockquote>
&lt;script type="text/javascript"&gt;breakstuff();&lt;/script&gt;""" <script type="text/javascript">breakstuff();</script>"""
) )
self.assertEqual(end_string, process_markdown(start_string)) self.assertEqual(end_string, markdown(start_string))
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment