def set_preference(wrapper, arguments, traverser): """Tests set preference calls for non-root preferences branches against dangerous values.""" parent = getattr(wrapper, "parent") if not (arguments and parent and parent.is_global and parent.value.get("preference_branch")): return arg = traverser._traverse_node(arguments[0]) if arg.is_literal(): pref = (parent.value["preference_branch"] + actions._get_as_str(arg)) msg = actions.test_preference(pref) if msg: kw = {"err_id": ("testcases_javascript_actions", "_call_expression", "called_set_preference"), "warning": "Attempt to set a dangerous preference"} if isinstance(msg, dict): kw.update(msg) else: kw["description"] = msg traverser.warning(**kw)
def PageMod(args, traverser, node, wrapper): """ This is the function that is called in Jetpack to modify the contents of a page with a "content script". This function needs to analyze he first parameter. If it is an object and if that object contains a "contentScript" string, that string needs to be passed to the validator.testcases.scripting library for testing as its own JS script file. """ if not args: return pm_properties = traverser._traverse_node(args[0]) if not pm_properties.has_property("contentScript"): return content_script = pm_properties.get(traverser, "contentScript") if not content_script.is_literal(): return content_script = actions._get_as_str(content_script.get_literal_value()) if not content_script.strip(): return import validator.testcases.scripting as sub_scripting sub_scripting.test_js_file( traverser.err, traverser.filename, content_script, line=traverser.line, context=traverser.context)
def set_preference(wrapper, arguments, traverser): """Tests set preference calls for non-root preferences branches against dangerous values.""" if len(arguments) < 1: return parent = getattr(wrapper, 'parent', None) arg = traverser._traverse_node(arguments[0]) if arg.is_literal(): pref = actions._get_as_str(arg) # If we're being called on a preference branch other than the root, # prepend its branch name to the passed preference name. if (parent and parent.is_global and parent.value.get('preference_branch')): pref = parent.value['preference_branch'] + pref else: drop_pref_messages(arg) kw = { 'err_id': ('testcases_javascript_actions', '_call_expression', 'called_set_preference'), 'warning': 'Attempt to set a dangerous preference' } # Local import to prevent import loop. from validator.testcases.regex import validate_pref validate_pref(pref, traverser, kw, wrapper=arg)
def set_contentScript(value, traverser): """Warns when values are assigned to the `contentScript` properties, which are essentially the same as calling `eval`.""" if value.is_literal(): content_script = actions._get_as_str(value) # Avoid import loop. from validator.testcases.scripting import test_js_file test_js_file(traverser.err, traverser.filename, content_script, line=traverser.line, context=traverser.context) else: traverser.warning( err_id=('testcases_javascript_instanceproperties', 'contentScript', 'set_non_literal'), warning='`contentScript` properties should not be used', description='Creating content scripts from dynamic values ' 'is dangerous and error-prone. Please use a separate ' 'JavaScript file, along with the ' '`contentScriptFile` property instead.', signing_help='Please do not use the `contentScript` property ' 'in any add-ons submitted for automated signing.', signing_severity='high')
def set_preference(wrapper, arguments, traverser): """Tests set preference calls for non-root preferences branches against dangerous values.""" if len(arguments) < 1: return parent = getattr(wrapper, 'parent', None) arg = traverser._traverse_node(arguments[0]) if arg.is_literal(): pref = actions._get_as_str(arg) # If we're being called on a preference branch other than the root, # prepend its branch name to the passed preference name. if (parent and parent.is_global and parent.value.get('preference_branch')): pref = parent.value['preference_branch'] + pref else: drop_pref_messages(arg) kw = {'err_id': ('testcases_javascript_actions', '_call_expression', 'called_set_preference'), 'warning': 'Attempt to set a dangerous preference'} # Local import to prevent import loop. from validator.testcases.regex import validate_pref validate_pref(pref, traverser, kw, wrapper=arg)
def createElement(args, traverser, node, wrapper): """Handles createElement calls""" if not args: return simple_args = map(traverser._traverse_node, args) first_as_str = actions._get_as_str(simple_args[0].get_literal_value()) if first_as_str.lower() == u'script': _create_script_tag(traverser) elif not simple_args[0].is_literal(): _create_variable_element(traverser)
def create_preference_branch(arguments, traverser, node, wrapper): """Creates a preference branch, which can be used for testing composed preference names.""" if arguments: arg = traverser._traverse_node(arguments[0]) if arg.is_literal(): # Avoid import loop from predefinedentities import build_quick_xpcom res = build_quick_xpcom('createInstance', 'nsIPrefBranch', traverser, wrapper=True) res.value['preference_branch'] = actions._get_as_str(arg) return res
def createElementNS(args, traverser, node, wrapper): """Handles createElementNS calls""" if not args or len(args) < 2: return simple_args = map(traverser._traverse_node, args) second_as_str = actions._get_as_str(simple_args[1].get_literal_value()) if 'script' in second_as_str.lower(): _create_script_tag(traverser) elif not simple_args[1].is_literal(): _create_variable_element(traverser)
def createElement(args, traverser, node, wrapper): """Handles createElement calls""" if not args: return simple_args = map(traverser._traverse_node, args) first_as_str = actions._get_as_str(simple_args[0].get_literal_value()) if first_as_str.lower() == u"script": _create_script_tag(traverser) elif not simple_args[0].is_literal(): _create_variable_element(traverser)
def createElementNS(args, traverser, node, wrapper): """Handles createElementNS calls""" if not args or len(args) < 2: return simple_args = map(traverser._traverse_node, args) second_as_str = actions._get_as_str(simple_args[1].get_literal_value()) if "script" in second_as_str.lower(): _create_script_tag(traverser) elif not simple_args[1].is_literal(): _create_variable_element(traverser)
def setAttribute(args, traverser, node, wrapper): """This ensures that setAttribute calls don't set on* attributes""" if not args: return simple_args = [traverser._traverse_node(a) for a in args] first_as_str = actions._get_as_str(simple_args[0].get_literal_value()) if first_as_str.lower().startswith("on"): warn(traverser.err, filename=traverser.filename, line=traverser.line, column=traverser.position, context=traverser.context, violation_type="setAttribute-on")
def setAttribute(args, traverser, node, wrapper): """This ensures that setAttribute calls don't set on* attributes""" if not args: return simple_args = [traverser._traverse_node(a) for a in args] first_as_str = actions._get_as_str(simple_args[0].get_literal_value()) if first_as_str.lower().startswith("on"): traverser.warning( err_id=("testcases_javascript_instanceactions", "setAttribute", "setting_on*"), warning="on* attribute being set using setAttribute", description="To prevent vulnerabilities, event handlers (like " "'onclick' and 'onhover') should always be defined " "using addEventListener.", signing_severity="medium")
def setAttribute(args, traverser, node, wrapper): """This ensures that setAttribute calls don't set on* attributes""" if not args: return simple_args = [traverser._traverse_node(a) for a in args] first_as_str = actions._get_as_str(simple_args[0].get_literal_value()) if first_as_str.lower().startswith("on"): traverser.err.notice( err_id=("testcases_javascript_instanceactions", "setAttribute", "setting_on*"), notice="on* attribute being set using setAttribute", description="To prevent vulnerabilities, event handlers (like " "'onclick' and 'onhover') should always be defined " "using addEventListener.", filename=traverser.filename, line=traverser.line, column=traverser.position, context=traverser.context)
def setAttribute(args, traverser, node): """This ensures that setAttribute calls don't set on* attributes""" if not args: return simple_args = [traverser._traverse_node(a) for a in args] first_as_str = actions._get_as_str(simple_args[0].get_literal_value()) if first_as_str.lower().startswith("on"): traverser.err.notice( err_id=("testcases_javascript_instanceactions", "setAttribute", "setting_on*"), notice="on* attribute being set using setAttribute", description="To prevent vulnerabilities, event handlers (like " "'onclick' and 'onhover') should always be defined " "using addEventListener.", filename=traverser.filename, line=traverser.line, column=traverser.position, context=traverser.context)
def set_contentScript(value, traverser): """Warns when values are assigned to the `contentScript` properties, which are essentially the same as calling `eval`.""" if value.is_literal(): content_script = actions._get_as_str(value) # Avoid import loop. from validator.testcases.scripting import test_js_file test_js_file( traverser.err, traverser.filename, content_script, line=traverser.line, context=traverser.context) else: traverser.warning( err_id=("testcases_javascript_instanceproperties", "contentScript", "set_non_literal"), warning="`contentScript` properties should not be used", description="Creating content scripts from dynamic values " "is dangerous and error-prone. Please use a separate " "JavaScript file, along with the " "`contentScriptFile` property instead.", signing_severity="high")
def setAttribute(args, traverser, node, wrapper): """This ensures that setAttribute calls don't set on* attributes""" if not args: return simple_args = [traverser._traverse_node(a) for a in args] first_as_str = actions._get_as_str(simple_args[0].get_literal_value()) if first_as_str.lower().startswith('on'): traverser.warning( err_id=('testcases_javascript_instanceactions', 'setAttribute', 'setting_on*'), warning='on* attribute being set using setAttribute', description='To prevent vulnerabilities, event handlers (like ' "'onclick' and 'onhover') should always be defined " 'using addEventListener.', signing_help='Please use `addEventListener` any place you might ' 'otherwise create event listener attributes. Event ' 'listener attributes will not be accepted in add-ons ' 'submitted for automated signing in any instance ' 'where they may be reasonably avoided.', signing_severity='medium')
def set_contentScript(value, traverser): """Warns when values are assigned to the `contentScript` properties, which are essentially the same as calling `eval`.""" if value.is_literal(): content_script = actions._get_as_str(value) # Avoid import loop. from validator.testcases.scripting import test_js_file test_js_file( traverser.err, traverser.filename, content_script, line=traverser.line, context=traverser.context) else: traverser.warning( err_id=('testcases_javascript_instanceproperties', 'contentScript', 'set_non_literal'), warning='`contentScript` properties should not be used', description='Creating content scripts from dynamic values ' 'is dangerous and error-prone. Please use a separate ' 'JavaScript file, along with the ' '`contentScriptFile` property instead.', signing_help='Please do not use the `contentScript` property ' 'in any add-ons submitted for automated signing.', signing_severity='high')
def _process_literal(type_, literal): if type_ == "string": return actions._get_as_str(literal) elif type_ == "num": return actions._get_as_num(literal) return literal
"value": {u"classes": {"xpcom_wildcard": True, "value": {u"createInstance": {"return": xpcom_const("createInstance")}, u"getService": {"return": xpcom_const("getService")}}}, "utils": {"value": {u"evalInSandbox": {"dangerous": True}, u"import": {"dangerous": lambda a, t, e: a and _get_as_str(t(a[0]).get_literal_value()) .count("ctypes.jsm")}}}, u"interfaces": {"value": {u"nsIXMLHttpRequest": {"xpcom_map": lambda: GLOBAL_ENTITIES["XMLHttpRequest"]}, u"nsIAccessibleRetrieval": {"xpcom_map": lambda: INTERFACES["nsIAccessibleRetrieval"]}, u"nsIBrowserSearchService": {"xpcom_map": lambda: INTERFACES["nsIBrowserSearchService"]}, u"nsICategoryManager": {"xpcom_map":
{"value": lambda t: build_quick_xpcom("getService", "nsIWindowWatcher", t)}}}, u"document": {"value": {u"title": {"overwriteable": True, "readonly": False}, u"defaultView": {"value": lambda t: {"value": GLOBAL_ENTITIES}}, u"createElement": {"dangerous": lambda a, t, e: not a or _get_as_str(t(a[0])).lower() == "script"}, u"createElementNS": {"dangerous": lambda a, t, e: not a or _get_as_str(t(a[0])).lower() == "script"}, u"getSelection": {"return": call_definitions.document_getSelection}, u"loadOverlay": {"dangerous": lambda a, t, e: not a or not _get_as_str(t(a[0])).lower() .startswith(("chrome:", "resource:"))}, u"xmlEncoding": entity("document.xmlEncoding"), u"xmlVersion": entity("document.xmlVersion"), u"xmlStandalone": entity("document.xmlStandalone")}},
def string_global(wrapper, arguments, traverser): if not arguments: return JSWrapper('', traverser=traverser) arg = traverser._traverse_node(arguments[0]) value = actions._get_as_str(arg.get_literal_value()) return JSWrapper(value, traverser=traverser)
} }, u'document': { 'value': { u'title': { 'overwriteable': True, 'readonly': False }, u'defaultView': { 'value': lambda t: { 'value': GLOBAL_ENTITIES } }, u'loadOverlay': { 'dangerous': lambda a, t, e: not a or not _get_as_str(t(a[0])).lower(). startswith(('chrome:', 'resource:')) }, u'write': entity('document.write'), u'writeln': entity('document.write') } }, # The nefariuos timeout brothers! u'setTimeout': { 'dangerous': actions._call_settimeout }, u'setInterval': { 'dangerous': actions._call_settimeout }, u'require': { 'dangerous': actions._call_require
u"navigator": {"value": {u"wifi": {"dangerous": True}, u"geolocation": {"dangerous": True}}}, u"Components": { "readonly": True, "value": { u"classes": { "xpcom_wildcard": True, "value": { u"createInstance": {"return": xpcom_const("createInstance")}, u"getService": {"return": xpcom_const("getService")}, }, }, "utils": { "value": { u"evalInSandbox": {"dangerous": True}, u"import": { "dangerous": lambda a, t, e: a and _get_as_str(t(a[0]).get_literal_value()).count("ctypes.jsm") }, } }, u"interfaces": { "value": { u"nsIXMLHttpRequest": {"xpcom_map": lambda: GLOBAL_ENTITIES["XMLHttpRequest"]}, u"nsIAccessibleRetrieval": {"xpcom_map": lambda: INTERFACES["nsIAccessibleRetrieval"]}, u"nsICategoryManager": {"xpcom_map": lambda: INTERFACES["nsICategoryManager"]}, u"nsIComponentRegistrar": {"xpcom_map": lambda: INTERFACES["nsIComponentRegistrar"]}, u"nsIJSON": {"xpcom_map": lambda: INTERFACES["nsIJSON"]}, u"nsIImapMailFolderSink": {"xpcom_map": lambda: INTERFACES["nsIImapMailFolderSink"]}, u"nsIImapProtocol": {"xpcom_map": lambda: INTERFACES["nsIImapProtocol"]}, u"nsIMsgSearchScopeTerm": {"xpcom_map": lambda: INTERFACES["nsIMsgSearchScopeTerm"]}, u"nsIMsgThread": {"xpcom_map": lambda: INTERFACES["nsIMsgThread"]}, u"nsIObserverService": {"xpcom_map": lambda: INTERFACES["nsIObserverService"]},
def _process_literal(type_, literal): if type_ == 'string': return actions._get_as_str(literal) elif type_ == 'num': return actions._get_as_num(literal) return literal
'Any code which makes use of the `ctypes` API ' 'must undergo manual code review for at least one ' 'submission.'), 'signing_severity': 'high'}}, u'document': {'value': {u'title': {'overwriteable': True, 'readonly': False}, u'defaultView': {'value': lambda t: {'value': GLOBAL_ENTITIES}}, u'loadOverlay': {'dangerous': lambda a, t, e: not a or not _get_as_str(t(a[0])).lower() .startswith(('chrome:', 'resource:'))}, u'write': entity('document.write'), u'writeln': entity('document.write')}}, # The nefariuos timeout brothers! u'setTimeout': {'dangerous': actions._call_settimeout}, u'setInterval': {'dangerous': actions._call_settimeout}, u'require': {'dangerous': actions._call_require}, u'encodeURI': {'readonly': True}, u'decodeURI': {'readonly': True}, u'encodeURIComponent': {'readonly': True}, u'decodeURIComponent': {'readonly': True}, u'escape': {'readonly': True}, u'unescape': {'readonly': True},
} }, u"document": { "value": { u"title": { "overwriteable": True, "readonly": False }, u"defaultView": { "value": lambda t: { "value": GLOBAL_ENTITIES } }, u"createElement": { "dangerous": lambda a, t, e: not a or _get_as_str(t(a[0])).lower() == "script" and "Dynamic creation of script nodes can be " "unsafe if contents are not static or are " "otherwise unsafe, or if `src` is remote." }, u"createElementNS": { "dangerous": lambda a, t, e: not a or _get_as_str(t(a[0])).lower() == "script" and "Dynamic creation of script nodes can be " "unsafe if contents are not static or are " "otherwise unsafe, or if `src` is remote." }, u"getSelection": { "return": call_definitions.document_getSelection }, u"loadOverlay": {
u"null": {"literal": lambda t: JSWrapper(None, traverser=t)}, u"Cc": {"readonly": False, "value": lambda t: GLOBAL_ENTITIES["Components"]["value"]["classes"]}, u"Ci": {"readonly": False, "value": lambda t: GLOBAL_ENTITIES["Components"]["value"]["interfaces"]}, u"Cu": {"readonly": False, "value": lambda t: GLOBAL_ENTITIES["Components"]["value"]["utils"]}, u"Services": { "value": { u"scriptloader": {"dangerous": True}, u"wm": {"value": lambda t: build_quick_xpcom("getService", "nsIWindowMediator", t)}, u"ww": {"value": lambda t: build_quick_xpcom("getService", "nsIWindowWatcher", t)}, } }, u"document": { "value": { u"title": {"overwriteable": True, "readonly": False}, u"defaultView": {"value": lambda t: {"value": GLOBAL_ENTITIES}}, u"createElement": {"dangerous": lambda a, t, e: not a or _get_as_str(t(a[0])).lower() == "script"}, u"createElementNS": {"dangerous": lambda a, t, e: not a or _get_as_str(t(a[0])).lower() == "script"}, u"getSelection": {"return": call_definitions.document_getSelection}, u"loadOverlay": { "dangerous": lambda a, t, e: not a or not _get_as_str(t(a[0])).lower().startswith(("chrome:", "resource:")) }, u"write": entity("document.write"), u"writeln": entity("document.write"), u"xmlEncoding": entity("document.xmlEncoding"), u"xmlVersion": entity("document.xmlVersion"), u"xmlStandalone": entity("document.xmlStandalone"), } }, # The nefariuos timeout brothers! u"setTimeout": {"dangerous": actions._call_settimeout},
t)}, u"ww": {"value": lambda t: build_quick_xpcom("getService", "nsIWindowWatcher", t)}}}, u"document": {"value": {u"title": {"overwriteable": True, "readonly": False}, u"createElement": {"dangerous": lambda a, t, e: not a or _get_as_str(t(a[0]).get_literal_value()) .lower() == "script"}, u"createElementNS": {"dangerous": lambda a, t, e: not a or _get_as_str(t(a[0]).get_literal_value()) .lower() == "script"}, u"loadOverlay": {"dangerous": lambda a, t, e: not a or not _get_as_str(t(a[0]).get_literal_value()) .lower() .startswith(("chrome:", "resource:"))}}},