Skip to content

Commit 408be62

Browse files
Merge pull request #88 from w3c/role-attr
Replace allowlist of html attributes with check for on* attributes
2 parents 525b150 + 0b130bd commit 408be62

File tree

3 files changed

+7
-32
lines changed

3 files changed

+7
-32
lines changed

src/feedvalidator/content.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,11 @@ def startElementNS(self, name, qname, attrs):
153153
elif name not in HTMLValidator.acceptable_elements:
154154
self.log(SecurityRisk({'tag':name}))
155155
for ns,attr in attrs.getNames():
156-
if not ns and attr not in HTMLValidator.acceptable_attributes:
156+
if not ns:
157157
if attr == 'style':
158158
for value in checkStyle(attrs.get((ns,attr))):
159159
self.log(DangerousStyleAttr({"attr":attr, "value":value}))
160-
else:
160+
elif attr.startswith("on"):
161161
self.log(SecurityRiskAttr({'attr':attr}))
162162
elif qname == 'http://www.w3.org/2000/svg':
163163
if name not in HTMLValidator.svg_elements:

src/feedvalidator/validators.py

+3-28
Original file line numberDiff line numberDiff line change
@@ -134,29 +134,6 @@ class HTMLValidator:
134134
'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'time', 'tfoot', 'th',
135135
'thead', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'noscript', 'wbr']
136136

137-
acceptable_attributes = ['abbr', 'accept', 'accept-charset', 'accesskey',
138-
'action', 'align', 'allow', 'allowfullscreen', 'allowpaymentrequest', 'alt', 'as', 'autoplay', 'autocapitalize', 'autocomplete', 'autofocus', 'autoplay', 'axis',
139-
'background', 'balance', 'bgcolor', 'bgproperties', 'border',
140-
'bordercolor', 'bordercolordark', 'bordercolorlight', 'bottompadding',
141-
'cellpadding', 'cellspacing', 'ch', 'challenge', 'char', 'charoff',
142-
'choff', 'charset', 'checked', 'cite', 'class', 'clear', 'color', 'cols',
143-
'colspan', 'compact', 'contenteditable', 'coords', 'crossorigin', 'data', 'datafld',
144-
'datapagesize', 'datasrc', 'datetime', 'decoding', 'default', 'delay', 'dir', 'dirname',
145-
'disabled', 'download', 'draggable', 'dynsrc', 'enctype','end', 'enterkeyhint', 'face', 'for',
146-
'form', 'formenctype', 'frame', 'galleryimg', 'gutter', 'headers', 'height', 'hidefocus',
147-
'hidden', 'high', 'href', 'hreflang', 'hspace', 'icon', 'id', 'inputmode',
148-
'is', 'ismap', 'itemid', 'itemprop', 'itemref', 'itemscope', 'itemtype', 'kind','keytype', 'label', 'lang', 'leftspacing', 'loading', 'list', 'longdesc',
149-
'loop', 'loopcount', 'loopend', 'loopstart', 'low', 'lowsrc', 'max',
150-
'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nohref', 'nonce',
151-
'noshade', 'nowrap', 'open', 'optimum', 'pattern', 'ping', 'placeholder', 'playsinline', 'point-size', 'poster', 'preload',
152-
'prompt', 'pqg', 'radiogroup', 'readonly', 'referrerpolicy', 'rel', 'repeat-max',
153-
'repeat-min', 'replace', 'required', 'rev', 'reversed', 'rightspacing', 'rows',
154-
'rowspan', 'rules', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'spellcheck', 'src',
155-
'srclang', 'srcset',
156-
'start', 'step', 'summary', 'suppress', 'tabindex', 'target', 'template',
157-
'title', 'toppadding', 'translate', 'type', 'unselectable', 'usemap', 'urn', 'valign',
158-
'value', 'variable', 'volume', 'vspace', 'vrml', 'width', 'wrap',
159-
'xml:lang', 'xmlns']
160137

161138
acceptable_css_properties = ['azimuth', 'background', 'background-color',
162139
'border', 'border-bottom', 'border-bottom-color', 'border-bottom-style',
@@ -280,10 +257,8 @@ def handle_tag(self, tag, attributes, text):
280257
if name.lower() == 'style':
281258
for evil in checkStyle(value):
282259
self.log(DangerousStyleAttr({"parent":self.element.parent.name, "element":self.element.name, "attr":"style", "value":evil}))
283-
elif name.lower() not in self.acceptable_attributes:
284-
# data-* attributes are acceptable
285-
if name.lower()[:5] != "data-":
286-
self.log(SecurityRiskAttr({"parent":self.element.parent.name, "element":self.element.name, "attr":name}))
260+
elif name.lower().startswith("on"):
261+
self.log(SecurityRiskAttr({"parent":self.element.parent.name, "element":self.element.name, "attr":name}))
287262

288263

289264
#
@@ -321,7 +296,7 @@ def startElementNS(self, name, qname, attrs):
321296
if attr[1].lower() == 'style':
322297
for value in checkStyle(attrs.get(attr)):
323298
self.log(DangerousStyleAttr({"parent":self.parent.name, "element":self.name, "attr":attr[1], "value":value}))
324-
elif attr[1].lower() not in HTMLValidator.acceptable_attributes:
299+
elif attr[1].lower().startswith("on"):
325300
self.log(SecurityRiskAttr({"parent":self.parent.name, "element":self.name, "attr":attr[1]}))
326301
self.push(htmlEater(), self.name, attrs)
327302
if name.lower() not in HTMLValidator.acceptable_elements:

testcases/atom/3.1.1.3/bogus_xhtml_attr.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Author: Sam Ruby <[email protected]>
55

66
<!--
77
Description: xhtml content with bogus attribute
8-
Expect: SecurityRiskAttr{attr:bogus}
8+
Expect: SecurityRiskAttr{attr:onbug}
99
-->
1010

1111
<feed xmlns="http://www.w3.org/2005/Atom">
@@ -25,7 +25,7 @@ Expect: SecurityRiskAttr{attr:bogus}
2525
<updated>2003-12-13T18:30:02Z</updated>
2626
<summary type="xhtml">
2727
<div xmlns="http://www.w3.org/1999/xhtml">
28-
This is <b bogus="true">XHTML</b> content.
28+
This is <b onbug="true">XHTML</b> content.
2929
</div>
3030
</summary>
3131
</entry>

0 commit comments

Comments
 (0)