From b6c3e5d7979a50e241abc26b699db8ea74d06c01 Mon Sep 17 00:00:00 2001 From: James Cammarata Date: Tue, 4 Aug 2015 13:30:47 -0400 Subject: [PATCH] Validate variable names given in set_fact Fixes #11851 --- lib/ansible/plugins/action/set_fact.py | 39 ++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/ansible/plugins/action/set_fact.py b/lib/ansible/plugins/action/set_fact.py index 10ff6f23225..5822fb3f083 100644 --- a/lib/ansible/plugins/action/set_fact.py +++ b/lib/ansible/plugins/action/set_fact.py @@ -17,10 +17,45 @@ from __future__ import (absolute_import, division, print_function) __metaclass__ = type +import ast + +from six import string_types + from ansible.errors import AnsibleError from ansible.plugins.action import ActionBase from ansible.utils.boolean import boolean +def isidentifier(ident): + """ + Determines, if string is valid Python identifier using the ast module. + Orignally posted at: http://stackoverflow.com/a/29586366 + """ + + if not isinstance(ident, string_types): + return False + + try: + root = ast.parse(ident) + except SyntaxError: + return False + + if not isinstance(root, ast.Module): + return False + + if len(root.body) != 1: + return False + + if not isinstance(root.body[0], ast.Expr): + return False + + if not isinstance(root.body[0].value, ast.Name): + return False + + if root.body[0].value.id != ident: + return False + + return True + class ActionModule(ActionBase): TRANSFERS_FILES = False @@ -30,6 +65,10 @@ class ActionModule(ActionBase): if self._task.args: for (k, v) in self._task.args.iteritems(): k = self._templar.template(k) + + if not isidentifier(k): + return dict(failed=True, msg="The variable name '%s' is not valid. Variables must start with a letter or underscore character, and contain only letters, numbers and underscores." % k) + if isinstance(v, basestring) and v.lower() in ('true', 'false', 'yes', 'no'): v = boolean(v) facts[k] = v