swimlane / pyattck

A Python package to interact with the Mitre ATT&CK Framework

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bad paths to constructor do not raise error

mcarpenter opened this issue · comments

Describe the bug
If a caller gives an incorrect JSON file path to the Attck constructor then this is silently ignored. This will likely lead to later runtime exceptions that are hard to diagnose.

To Reproduce
err.py:

#!/usr/bin/env python

from pyattck import Attck
attck = Attck(enterprise_attck_json='oopsy.json')
print(len(attck.enterprise.actors))

Running this produces error at the last line:

Traceback (most recent call last):
  File "./err.py", line 5, in <module>
    print(len(attck.enterprise.actors))
  File "/home/mjc/github/pyattck/pyattck/enterprise/enterprise.py", line 292, in actors
    for group in self.__attck['objects']:
TypeError: 'NoneType' object is not subscriptable

Expected behavior
The standard exception FileNotFoundError should be propagated from the call to open(). Instead, it is hidden from the caller by _read_from_disk() in configuration.py. I see two issues (anti-patterns) here:

  1. Check-then-open: just try to open the path as a file.
  2. Ignoring all subsequent exceptions (except: pass): remove.
    def __read_from_disk(cls, path):
        if os.path.exists(path) and os.path.isfile(path):
            try:
                with open(path) as f:
                    if path.endswith('.json'):
                        return json.load(f)
                    elif path.endswith('.yml') or path.endswith('.yaml'):
                        return yaml.load(f, Loader=yaml.FullLoader)
                    else:
                        raise UknownFileError(provided_value=path, known_values=['.json', '.yml', '.yaml'])
            except:
                pass
        return None

Small PR attached for this one file issue. I lost a couple of hours to this (path with dash instead of underscore, arg!).

There are many other occurrences of except: pass or except: return None throughout the project. Almost all of those could/should be improved. I don't have the context for the original author's decision so difficult to say what they were expecting might fail. Example from technique.py:

        try:
            for item in self._RELATIONSHIPS[self.stix]:
                if item in item_dict:
                    return_list.append(PreAttckActor(preattck_obj=self.__preattck_obj, **item_dict[item]))
        except:
            pass

Where did the author think this might fail? Is that okay? What error is actually raised? Should it really be ignored?

I will not be working through these other items but they should probably be on somebody's TODO list.

Thanks!