mirror of
https://github.com/caronc/apprise.git
synced 2025-01-07 14:39:51 +01:00
Hardening of custom plugin loading by ignore non-Python files (#853)
This commit is contained in:
parent
2057107590
commit
6144a79513
@ -63,7 +63,13 @@ def import_module(path, name):
|
||||
|
||||
except Exception as e:
|
||||
# module isn't loadable
|
||||
del sys.modules[name]
|
||||
try:
|
||||
del sys.modules[name]
|
||||
|
||||
except KeyError:
|
||||
# nothing to clean up
|
||||
pass
|
||||
|
||||
module = None
|
||||
|
||||
logger.debug(
|
||||
@ -200,6 +206,9 @@ UUID4_RE = re.compile(
|
||||
r'[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}',
|
||||
re.IGNORECASE)
|
||||
|
||||
# Validate if we're a loadable Python file or not
|
||||
VALID_PYTHON_FILE_RE = re.compile(r'.+\.py(o|c)?$', re.IGNORECASE)
|
||||
|
||||
# validate_regex() utilizes this mapping to track and re-use pre-complied
|
||||
# regular expressions
|
||||
REGEX_VALIDATE_LOOKUP = {}
|
||||
@ -1565,6 +1574,11 @@ def module_detection(paths, cache=True):
|
||||
# Since our plugin name can conflict (as a module) with another
|
||||
# we want to generate random strings to avoid steping on
|
||||
# another's namespace
|
||||
if not (path and VALID_PYTHON_FILE_RE.match(path)):
|
||||
# Ignore file/module type
|
||||
logger.trace('Plugin Scan: Skipping %s', path)
|
||||
return None
|
||||
|
||||
module_name = hashlib.sha1(path.encode('utf-8')).hexdigest()
|
||||
module_pyname = "{prefix}.{name}".format(
|
||||
prefix='apprise.custom.module', name=module_name)
|
||||
|
@ -2015,6 +2015,21 @@ def test_parse_list():
|
||||
])
|
||||
|
||||
|
||||
def test_import_module(tmpdir):
|
||||
"""utils: imort_module testing
|
||||
"""
|
||||
# Prepare ourselves a file to work with
|
||||
bad_file_base = tmpdir.mkdir('a')
|
||||
bad_file = bad_file_base.join('README.md')
|
||||
bad_file.write(cleandoc("""
|
||||
I'm a README file, not a Python one.
|
||||
|
||||
I can't be loaded
|
||||
"""))
|
||||
assert utils.import_module(str(bad_file), 'invalidfile1') is None
|
||||
assert utils.import_module(str(bad_file_base), 'invalidfile2') is None
|
||||
|
||||
|
||||
def test_module_detection(tmpdir):
|
||||
"""utils: test_module_detection() testing
|
||||
"""
|
||||
@ -2041,13 +2056,20 @@ def test_module_detection(tmpdir):
|
||||
pass
|
||||
"""))
|
||||
|
||||
notify_ignore = notify_hook_a_base.join('README.md')
|
||||
notify_ignore.write(cleandoc("""
|
||||
We're not a .py file, so this file gets gracefully skipped
|
||||
"""))
|
||||
|
||||
# Not previously loaded
|
||||
assert 'clihook' not in common.NOTIFY_SCHEMA_MAP
|
||||
|
||||
# load entry by string
|
||||
utils.module_detection(str(notify_hook_a))
|
||||
utils.module_detection(str(notify_ignore))
|
||||
utils.module_detection(str(notify_hook_a_base))
|
||||
|
||||
assert len(utils.PATHS_PREVIOUSLY_SCANNED) == 1
|
||||
assert len(utils.PATHS_PREVIOUSLY_SCANNED) == 3
|
||||
assert len(common.NOTIFY_CUSTOM_MODULE_MAP) == 1
|
||||
|
||||
# Now loaded
|
||||
@ -2057,7 +2079,7 @@ def test_module_detection(tmpdir):
|
||||
utils.module_detection([str(notify_hook_a)])
|
||||
|
||||
# No changes to our path
|
||||
assert len(utils.PATHS_PREVIOUSLY_SCANNED) == 1
|
||||
assert len(utils.PATHS_PREVIOUSLY_SCANNED) == 3
|
||||
assert len(common.NOTIFY_CUSTOM_MODULE_MAP) == 1
|
||||
|
||||
# Reset our variables for the next test
|
||||
|
Loading…
Reference in New Issue
Block a user