Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bad paths to constructor do not raise error #93

Closed
mcarpenter opened this issue Feb 10, 2022 · 2 comments · Fixed by #95
Closed

Bad paths to constructor do not raise error #93

mcarpenter opened this issue Feb 10, 2022 · 2 comments · Fixed by #95
Assignees
Labels
enhancement New feature or request

Comments

@mcarpenter
Copy link
Contributor

mcarpenter commented Feb 10, 2022

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
@mcarpenter
Copy link
Contributor Author

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.

@mcarpenter
Copy link
Contributor Author

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants