Adding to Nitely's answer which was great but slightly incomplete: I also recommend using Bleach, but if you want to use it to pre-approve safe CSS styles you need to use Bleach CSS Sanitizer (separate pip install to the vanilla bleach package), which makes for a slightly different code set-up to Nitely's.
We use the below in our Django project forms.py file (using Django-CKEditor as the content widget) to sanitize the data for our user-input ReportPages.
import bleach
from bleach.css_sanitizer import CSSSanitizer
from django.conf import settings
css_sanitizer = CSSSanitizer(allowed_css_properties=settings.BLEACH_VALID_STYLES)
class ReportPageForm(forms.ModelForm):
content = forms.CharField(widget=CKEditorWidget())
class Meta:
model = ReportPage
fields = ('name', 'content')
def clean_content(self):
content = self.cleaned_data['content']
cleaned_content = bleach.clean(
content,
tags=settings.BLEACH_VALID_TAGS,
attributes=settings.BLEACH_VALID_ATTRS,
protocols=settings.BLEACH_VALID_PROTOCOLS,
css_sanitizer=css_sanitizer,
strip=True
)
We include strip=True to remove mark-up that is escaped from the form content. We also include protocols so that any href attrs (for 'a' tags) and src attrs (for 'img' tags) must be https (http and mailto are enabled by default, which we wanted turned off).
For completeness' sake, inside our settings.py file we define the following as valid mark-up for our purposes:
BLEACH_VALID_TAGS = (
'a', 'abbr', 'acronym', 'b', 'blockquote', 'br', 'code',
'dd', 'div', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'hr', 'i', 'img', 'li', 'ol', 'p', 'pre', 'span', 'strike',
'strong', 'sub', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th',
'thead', 'tr', 'tt', 'u', 'ul'
)
BLEACH_VALID_ATTRS = {
'*': ['style', ], # allow all tags to have style attr
'p': ['align', ],
'a': ['href', 'rel'],
'img': ['src', 'alt', 'style'],
}
BLEACH_VALID_STYLES = (
'azimuth', 'background-color', 'border', 'border-bottom-color',
'border-collapse', 'border-color', 'border-left-color',
'border-right-color', 'border-top-color', 'clear',
'color','cursor', 'direction', 'display', 'elevation', 'float',
'font', 'font-family','font-size', 'font-style', 'font-variant',
'font-weight', 'height', 'letter-spacing', 'line-height',
'margin', 'margin-bottom', 'margin-left', 'margin-right',
'margin-top', 'overflow', 'padding', 'padding-bottom',
'padding-left', 'padding-right', 'padding-top', 'pause',
'pause-after', 'pause-before', 'pitch', 'pitch-range',
'richness', 'speak', 'speak-header', 'speak-numeral',
'speak-punctuation', 'speech-rate', 'stress', 'text-align',
'text-decoration', 'text-indent', 'unicode-bidi',
'vertical-align', 'voice-family', 'volume', 'white-space', 'width'
)
BLEACH_VALID_PROTOCOLS = ('https',)