From 4ec8954ab59b52e8a0770e2d23289a0d5d8e6754 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Thu, 20 Apr 2023 08:23:12 +0200 Subject: [PATCH] fix: improve url and jinja string escapes (#585) --- .../rules/CheckCommandInsteadOfModule.py | 3 +++ .../rules/CheckShellInsteadCommand.py | 11 ++--------- ansiblelater/standard.py | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/ansiblelater/rules/CheckCommandInsteadOfModule.py b/ansiblelater/rules/CheckCommandInsteadOfModule.py index 890d257..4902f5f 100644 --- a/ansiblelater/rules/CheckCommandInsteadOfModule.py +++ b/ansiblelater/rules/CheckCommandInsteadOfModule.py @@ -39,9 +39,12 @@ class CheckCommandInsteadOfModule(StandardBase): if task["action"]["__ansible_module__"] in commands: first_cmd_arg = self.get_first_cmd_arg(task) executable = os.path.basename(first_cmd_arg) + cmd = cmd = self.get_safe_cmd(task) + if ( first_cmd_arg and executable in modules and task["action"].get("warn", True) and "register" not in task + and not any(ch in cmd for ch in self.SHELL_PIPE_CHARS) ): errors.append( self.Error( diff --git a/ansiblelater/rules/CheckShellInsteadCommand.py b/ansiblelater/rules/CheckShellInsteadCommand.py index ec82305..b36a42f 100644 --- a/ansiblelater/rules/CheckShellInsteadCommand.py +++ b/ansiblelater/rules/CheckShellInsteadCommand.py @@ -1,5 +1,3 @@ -import re - from ansiblelater.standard import StandardBase @@ -22,13 +20,8 @@ class CheckShellInsteadCommand(StandardBase): if "executable" in task["action"]: continue - if "cmd" in task["action"]: - cmd = task["action"].get("cmd", []) - else: - cmd = " ".join(task["action"].get("__ansible_arguments__", [])) - - unjinja = re.sub(r"\{\{[^\}]*\}\}", "JINJA_VAR", cmd) - if not any(ch in unjinja for ch in "&|<>;$\n*[]{}?"): + cmd = self.get_safe_cmd(task) + if not any(ch in cmd for ch in self.SHELL_PIPE_CHARS): errors.append(self.Error(task["__line__"], self.helptext)) return self.Result(candidate.path, errors) diff --git a/ansiblelater/standard.py b/ansiblelater/standard.py index b439dc6..ae4b45e 100644 --- a/ansiblelater/standard.py +++ b/ansiblelater/standard.py @@ -8,6 +8,7 @@ import pathlib import re from abc import ABCMeta, abstractmethod from collections import defaultdict +from urllib.parse import urlparse import toolz import yaml @@ -44,6 +45,8 @@ class StandardExtendedMeta(StandardMeta, ABCMeta): class StandardBase(metaclass=StandardExtendedMeta): + SHELL_PIPE_CHARS = "&|<>;$\n*[]{}?" + @property @abstractmethod def sid(self): @@ -246,6 +249,22 @@ class StandardBase(metaclass=StandardExtendedMeta): return first_cmd_arg + @staticmethod + def get_safe_cmd(task): + if "cmd" in task["action"]: + cmd = task["action"].get("cmd", "") + else: + cmd = " ".join(task["action"].get("__ansible_arguments__", [])) + + cmd = re.sub(r"{{.+?}}", "JINJA_EXPRESSION", cmd) + cmd = re.sub(r"{%.+?%}", "JINJA_STATEMENT", cmd) + cmd = re.sub(r"{#.+?#}", "JINJA_COMMENT", cmd) + + parts = cmd.split() + parts = [p if not urlparse(p.strip('"').strip("'")).scheme else "URL" for p in parts] + + return " ".join(parts) + class Error: """Default error object created if a rule failed."""