fix: improve url and jinja string escapes (#585)

This commit is contained in:
Robert Kaussow 2023-04-20 08:23:12 +02:00 committed by GitHub
parent 5daceac699
commit 4ec8954ab5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 9 deletions

View File

@ -39,9 +39,12 @@ class CheckCommandInsteadOfModule(StandardBase):
if task["action"]["__ansible_module__"] in commands: if task["action"]["__ansible_module__"] in commands:
first_cmd_arg = self.get_first_cmd_arg(task) first_cmd_arg = self.get_first_cmd_arg(task)
executable = os.path.basename(first_cmd_arg) executable = os.path.basename(first_cmd_arg)
cmd = cmd = self.get_safe_cmd(task)
if ( if (
first_cmd_arg and executable in modules first_cmd_arg and executable in modules
and task["action"].get("warn", True) and "register" not in task 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( errors.append(
self.Error( self.Error(

View File

@ -1,5 +1,3 @@
import re
from ansiblelater.standard import StandardBase from ansiblelater.standard import StandardBase
@ -22,13 +20,8 @@ class CheckShellInsteadCommand(StandardBase):
if "executable" in task["action"]: if "executable" in task["action"]:
continue continue
if "cmd" in task["action"]: cmd = self.get_safe_cmd(task)
cmd = task["action"].get("cmd", []) if not any(ch in cmd for ch in self.SHELL_PIPE_CHARS):
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*[]{}?"):
errors.append(self.Error(task["__line__"], self.helptext)) errors.append(self.Error(task["__line__"], self.helptext))
return self.Result(candidate.path, errors) return self.Result(candidate.path, errors)

View File

@ -8,6 +8,7 @@ import pathlib
import re import re
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from collections import defaultdict from collections import defaultdict
from urllib.parse import urlparse
import toolz import toolz
import yaml import yaml
@ -44,6 +45,8 @@ class StandardExtendedMeta(StandardMeta, ABCMeta):
class StandardBase(metaclass=StandardExtendedMeta): class StandardBase(metaclass=StandardExtendedMeta):
SHELL_PIPE_CHARS = "&|<>;$\n*[]{}?"
@property @property
@abstractmethod @abstractmethod
def sid(self): def sid(self):
@ -246,6 +249,22 @@ class StandardBase(metaclass=StandardExtendedMeta):
return first_cmd_arg 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: class Error:
"""Default error object created if a rule failed.""" """Default error object created if a rule failed."""