1010import logging
1111import re
1212from typing import Any , Dict , Iterable , List , NoReturn , Optional , Tuple
13+ from string import Formatter
1314
1415from globber import match
1516
@@ -96,6 +97,16 @@ def parse_pattern(line: str) -> Tuple[bool, str, Optional[str], Optional[str]]:
9697 return sign , file_pattern , rule_pattern , message_pattern
9798
9899
100+ class SafeFormatter (Formatter ):
101+ """Prevent arbitrary field names - just allow numeric names, for positional arguments, with no formatting instructions."""
102+ valid_field_name_re = re .compile (r'^[0-9]{1,2}$' )
103+
104+ def get_field (self , field_name : str , args : List [str ], kwargs : Dict [str , str ]) -> Any :
105+ if not SafeFormatter .valid_field_name_re .match (field_name ):
106+ raise ValueError ('Invalid format string.' )
107+ return super ().get_field (field_name , args , kwargs )
108+
109+
99110def get_message_text (result : Dict [str , Any ]) -> Optional [str ]:
100111 """Process result to get message text."""
101112 message_object = result .get ('message' , None )
@@ -112,7 +123,8 @@ def get_message_text(result: Dict[str, Any]) -> Optional[str]:
112123 return message_text
113124 else :
114125 try :
115- return message_text .format (* message_arguments )
126+ form = SafeFormatter ()
127+ return form .format (message_text , * message_arguments )
116128 except Exception as err :
117129 LOG .warning ("Message arguments malformed: %s" , err )
118130 return message_text
0 commit comments