Example #1
0
def test_parse_line():
    t = threatmodel.ThreatModel()
    p = parser.SourceFileParser(t)

    lines = [{
        "line":
        "somecode.action(parameter) // @mitigates Path:To:Component against Threat with Control",
        "next_line":
        "other.action(parameter) // @mitigates Path:To:Component2 against Threat2 with Control2",
        "action": "mitigates",
        "threat": "Threat",
        "component": "Path:To:Component",
        "control": "Control",
        "annotation":
        "@mitigates Path:To:Component against Threat with Control",
        "code": "somecode.action(parameter)",
        "filename": "afile.js",
        "line_no": 66
    }]

    for line in lines:
        (data, source) = p.parse_line(line["line"], line["next_line"],
                                      line["filename"], line["line_no"])
        assert data == {
            "action": "mitigates",
            "threat": "Threat",
            "component": "Path:To:Component",
            "control": "Control"
        }
        assert source == {
            "annotation": line["annotation"],
            "code": line["code"],
            "filename": line["filename"],
            "line": line["line_no"]
        }
Example #2
0
def test_yaml_paser():
    t = threatmodel.ThreatModel()
    t.threat_library = threatmodel.ThreatLibrary()
    p = parser.YamlFileParser(t)

    yaml_string = """
        key1:
            key11:
                x-threatspec: "@threat A string threat"
            key12:
                x-threatspec:
                    - "@threat Array threat 1"
                    - "@threat Array threat 2"
        key2:
            key21:
                key211:
                    "x-threatspec":
                        "@threat Extended threat 1":
                            description: Extended description 1
                            impact: high
    """

    data = yaml.load(yaml_string, Loader=yaml.SafeLoader)
    p.parse_data(data, {}, "path/to/file")

    assert len(t.threat_library.threats) == 4

    assert "#a_string_threat" in t.threat_library.threats
    assert t.threat_library.threats[
        "#a_string_threat"].name == "A string threat"

    assert "#extended_threat_1" in t.threat_library.threats
    assert t.threat_library.threats["#extended_threat_1"].custom[
        "impact"] == "high"
Example #3
0
def test_parse_comment_line():
    t = threatmodel.ThreatModel()
    p = parser.SourceFileParser(t)

    lines = [{
        "line": "// A normal comment",
        "annotation": "A normal comment",
        "code": ""
    }, {
        "line": "somecode.action(parameter) // An inline comment",
        "annotation": "An inline comment",
        "code": "somecode.action(parameter)"
    }, {
        "line": "# A normal comment",
        "annotation": "A normal comment",
        "code": ""
    }, {
        "line": "somecode.action(parameter) # An inline comment",
        "annotation": "An inline comment",
        "code": "somecode.action(parameter)"
    }]

    for line in lines:
        (annotation, code) = p.parse_comment_line(line["line"])
        assert line["code"] == code
        assert line["annotation"] == annotation
Example #4
0
def test_parser_parse_annotation():
    t = threatmodel.ThreatModel()
    p = parser.Parser(t)

    annotations = [{
        "annotation":
        "@mitigates Path:To:Component against a multi word threat with a multi word control",
        "action": "mitigates",
        "component": "Path:To:Component",
        "threat": "a multi word threat",
        "control": "a multi word control"
    }, {
        "annotation":
        "@accepts a multi word threat to Path:To:Component with why it has been accepted",
        "action": "accepts",
        "threat": "a multi word threat",
        "component": "Path:To:Component",
        "details": "why it has been accepted"
    }, {
        "annotation":
        "@transfers a multi word threat from Path:To:Source to Path:To:Destination with why it has been transfered",
        "action": "transfers",
        "threat": "a multi word threat",
        "source_component": "Path:To:Source",
        "destination_component": "Path:To:Destination",
        "details": "why it has been transfered"
    }, {
        "annotation":
        "@exposes Path:To:Component to a multi word threat with how it is exposed",
        "action": "exposes",
        "threat": "a multi word threat",
        "component": "Path:To:Component",
        "details": "how it is exposed"
    }, {
        "annotation":
        "@connects Path:To:Source with Path:To:Destination with details about connection",
        "action": "connects",
        "source_component": "Path:To:Source",
        "destination_component": "Path:To:Destination",
        "direction": "with",
        "details": "details about connection"
    }, {
        "annotation": "@review Path:To:Component something worth noting",
        "action": "review",
        "component": "Path:To:Component",
        "details": "something worth noting"
    }, {
        "annotation": "@tests a multi word control for Path:To:Component",
        "action": "tests",
        "control": "a multi word control",
        "component": "Path:To:Component"
    }]

    for annotation in annotations:
        data = p.parse_annotation(annotation.pop("annotation"))
        assert data == annotation
Example #5
0
def test_strip():
    t = threatmodel.ThreatModel()
    t.threat_library = threatmodel.ThreatLibrary()
    p = parser.CommentParser(t)

    assert p.strip("* test ") == "test"
    assert p.strip(" * test ") == "test"
    assert p.strip("    * test ") == "test"
    assert p.strip("test  ") == "test"
    assert p.strip("  test") == "test"
    assert p.strip("  * test\n    attr: 42  ") == "test\n    attr: 42"
Example #6
0
def test_parse_control_extended_comment():
    t = threatmodel.ThreatModel()
    p = parser.SourceFileParser(t)

    comment_text = """
@control A Control (#controlid):
  description: |
    A multiline
    description
  cost: high
"""
    annotations = p.parse_comment(comment_text)
    assert len(annotations) == 1
    assert annotations[0]["control"] == "A Control (#controlid)"
    assert annotations[0]["description"] == "A multiline\ndescription\n"
    assert annotations[0]["cost"] == "high"
Example #7
0
def test_parse_threat_extended_comment():
    t = threatmodel.ThreatModel()
    p = parser.SourceFileParser(t)

    comment_text = """
@threat A Threat (#threatid):
  description: |
    A multiline
    description
  impact: high
"""
    annotations = p.parse_comment(comment_text)
    assert len(annotations) == 1
    assert annotations[0]["threat"] == "A Threat (#threatid)"
    assert annotations[0]["description"] == "A multiline\ndescription\n"
    assert annotations[0]["impact"] == "high"
Example #8
0
def test_parse_component_extended_comment_with_leading_stars():
    t = threatmodel.ThreatModel()
    p = parser.SourceFileParser(t)

    comment_text = """
         * @component Path:To:Component (#componentid):
         * description: |
         *   A multiline
         *   description
         * value: high
"""
    annotations = p.parse_comment(comment_text)
    assert len(annotations) == 1
    assert annotations[0]["component"] == "Path:To:Component (#componentid)"
    assert annotations[0]["description"] == "A multiline\ndescription\n"
    assert annotations[0]["value"] == "high"
Example #9
0
def test_parse_review_extended_comment_with_leading_stars():
    t = threatmodel.ThreatModel()
    p = parser.SourceFileParser(t)

    comment_text = """
         * @review Path:To:Component Check something:
         *   description: |
         *     A multiline
         *     description
         *   urgent: yes
"""
    annotations = p.parse_comment(comment_text)
    assert len(annotations) == 1
    assert annotations[0]["component"] == "Path:To:Component"
    assert annotations[0]["details"] == "Check something"
    assert annotations[0]["description"] == "A multiline\ndescription\n"
    assert annotations[0]["urgent"] == True
Example #10
0
    def __init__(self):
        self.threat_library = threatmodel.ThreatLibrary()
        self.control_library = threatmodel.ControlLibrary()
        self.component_library = threatmodel.ComponentLibrary()

        self.threatmodel = threatmodel.ThreatModel()
        self.threatmodel.threat_library = self.threat_library
        self.threatmodel.control_library = self.control_library
        self.threatmodel.component_library = self.component_library

        self.threatmodel.run_id = uuid.uuid4().hex
        logger.debug("Setting run id to {}".format(self.threatmodel.run_id))

        self.config = config.Config()
        self.parser = None
        self.reporter = None

        self.loaded_source_paths = {}
        self.loaded_library_paths = {}
Example #11
0
def test_source_file_parser_parse_comments():
    t = threatmodel.ThreatModel()
    p = parser.SourceFileParser(t)

    comments = [{
        "test":
        "@mitigates Path:To:Component against a multi word threat with a multi word control",
        "result": {
            "action": "mitigate",
            "component": "Path:To:Component",
            "threat": "a multi word threat",
            "control": "a multi word control"
        }
    }, {
        "test":
        "@accepts a multi word threat to Path:To:Component with why it has been accepted",
        "result": {
            "action": "accept",
            "threat": "a multi word threat",
            "component": "Path:To:Component",
            "details": "why it has been accepted"
        }
    }, {
        "test":
        "@transfers a multi word threat from Path:To:Source to Path:To:Destination with why it has been transfered",
        "result": {
            "action": "transfer",
            "threat": "a multi word threat",
            "source_component": "Path:To:Source",
            "destination_component": "Path:To:Destination",
            "details": "why it has been transfered"
        }
    }, {
        "test":
        "@exposes Path:To:Component to a multi word threat with how it is exposed",
        "result": {
            "action": "expose",
            "threat": "a multi word threat",
            "component": "Path:To:Component",
            "details": "how it is exposed"
        }
    }, {
        "test":
        "@connects Path:To:Source with Path:To:Destination with details about connection",
        "result": {
            "action": "connect",
            "source_component": "Path:To:Source",
            "destination_component": "Path:To:Destination",
            "direction": "with",
            "details": "details about connection"
        }
    }, {
        "test": "@review Path:To:Component something worth noting",
        "result": {
            "action": "review",
            "component": "Path:To:Component",
            "details": "something worth noting"
        }
    }, {
        "test": "@tests a multi word control for Path:To:Component",
        "result": {
            "action": "test",
            "control": "a multi word control",
            "component": "Path:To:Component"
        }
    }]

    for comment in comments:
        data = p.parse_comment(comment["test"])
        assert len(data) == 1
        data[0].pop("annotation")
        data[0].pop("line")
        assert data[0] == comment["result"]