1515
1616"""Main file for the pylint_secure_coding_standard plugin"""
1717
18+ import platform
19+
1820import astroid
1921
2022from pylint .checkers import BaseChecker
2123from pylint .interfaces import IAstroidChecker
2224
2325
26+ # ==============================================================================
27+ # Helper functions
28+
29+
30+ def _is_posix ():
31+ """Return True if the current system is POSIX-compatible."""
32+ # NB: we could simply use `os.name` instead of `platform.system()`. However, that solution would be difficult to
33+ # test using `mock` as a few modules (like `pytest`) actually use it internally...
34+ return platform .system () in ('Linux' , 'Darwin' )
35+
36+
2437# ==============================================================================
2538
2639
@@ -171,6 +184,15 @@ def _is_jsonpickle_encode_call(node):
171184 return False
172185
173186
187+ def _is_shlex_quote_call (node ):
188+ return not _is_posix () and (
189+ isinstance (node .func , astroid .Attribute )
190+ and isinstance (node .func .expr , astroid .Name )
191+ and node .func .expr .name == 'shlex'
192+ and node .func .attrname == 'quote'
193+ )
194+
195+
174196# ==============================================================================
175197
176198
@@ -235,6 +257,11 @@ class SecureCodingStandardChecker(BaseChecker):
235257 'avoid-os-popen' ,
236258 'Use of `os.popen()` should be avoided, as it internally uses `subprocess.Popen` with `shell=True`' ,
237259 ),
260+ 'E8011' : (
261+ 'Avoid using `shlex.quote()` on non-POSIX platforms' ,
262+ 'avoid-shlex-quote-on-non-posix' ,
263+ 'Use of `shlex.quote()` should be avoided on non-POSIX platforms (such as Windows)' ,
264+ ),
238265 }
239266
240267 options = {}
@@ -263,6 +290,8 @@ def visit_call(self, node):
263290 self .add_message ('replace-builtin-open' , node = node )
264291 elif isinstance (node .func , astroid .Name ) and (node .func .name in ('eval' , 'exec' )):
265292 self .add_message ('avoid-eval-exec' , node = node )
293+ elif _is_shlex_quote_call (node ):
294+ self .add_message ('avoid-shlex-quote-on-non-posix' , node = node )
266295
267296 def visit_import (self , node ):
268297 """
@@ -288,6 +317,8 @@ def visit_importfrom(self, node):
288317 self .add_message ('avoid-os-system' , node = node )
289318 elif node .modname == 'os' and [name for (name , _ ) in node .names if name == 'popen' ]:
290319 self .add_message ('avoid-os-popen' , node = node )
320+ elif not _is_posix () and node .modname == 'shlex' and [name for (name , _ ) in node .names if name == 'quote' ]:
321+ self .add_message ('avoid-shlex-quote-on-non-posix' , node = node )
291322
292323 def visit_with (self , node ):
293324 """
0 commit comments