diff --git a/docs/advanced_template.md b/docs/advanced_template.md
index 03918666..9d4e340e 100644
--- a/docs/advanced_template.md
+++ b/docs/advanced_template.md
@@ -30,33 +30,33 @@ Name|Description|Classification|Carried|Processed
Name|{{item.name}}
|:----|:----|
Description|{{item.description}}|
-Is Admin|{{item.isAdmin}}
+Is Admin|{{item.isAdmin}}|
Finding Count|{{item:call:getFindingCount}}|
-{{item.findings:if:
-
+{{item:call:getInScopeFindings:
**Threats**
-{{item.findings:repeat:
- {{{{item.id}}}} -- {{{{item.threat_id}}}} -- {{{{item.description}}}}
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
+
Targeted Element
- {{{{item.target}}}}
+ {{item:call:getFindingTarget}}
Severity
- {{{{item.severity}}}}
+ {{item:call:getFindingSeverity}}
Example Instances
- {{{{item.example}}}}
+ {{item:call:getFindingExample}}
Mitigations
- {{{{item.mitigations}}}}
+ {{item:call:getFindingMitigations}}
References
- {{{{item.references}}}}
+ {{item:call:getFindingReferences}}
}}
-}}
}
-## Boundaries
+## Boundaries
{boundaries:repeat:
Name|{{item.name}}
@@ -68,30 +68,29 @@ All Parents|{{item.parents:call:{{{{item.display_name:call:}}}}, }}|
Classification|{{item.maxClassification}}|
Finding Count|{{item:call:getFindingCount}}|
-{{item.findings:if:
-
+{{item:call:getInScopeFindings:
**Threats**
-{{item.findings:repeat:
- {{{{item.id}}}} -- {{{{item.threat_id}}}} -- {{{{item.description}}}}
- Targeted Element
- {{{{item.target}}}}
- Severity
- {{{{item.severity}}}}
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
+ Targeted Element
+ {{item:call:getFindingTarget}}
+ Severity
+ {{item:call:getFindingSeverity}}
Example Instances
- {{{{item.example}}}}
+ {{item:call:getFindingExample}}
Mitigations
- {{{{item.mitigations}}}}
+ {{item:call:getFindingMitigations}}
References
- {{{{item.references}}}}
-
+ {{item:call:getFindingReferences}}
}}
-}}
}
-## Assets
+
+## Assets
{assets:repeat:
Name|{{item.name}}|
@@ -101,30 +100,29 @@ In Scope|{{item.inScope}}|
Type|{{item:call:getElementType}}|
Finding Count|{{item:call:getFindingCount}}|
-{{item.findings:if:
-
+{{item:call:getInScopeFindings:
**Threats**
-{{item.findings:repeat:
- {{{{item.id}}}} -- {{{{item.threat_id}}}} -- {{{{item.description}}}}
- Targeted Element
- {{{{item.target}}}}
- Severity
- {{{{item.severity}}}}
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
+ Targeted Element
+ {{item:call:getFindingTarget}}
+ Severity
+ {{item:call:getFindingSeverity}}
Example Instances
- {{{{item.example}}}}
+ {{item:call:getFindingExample}}
Mitigations
- {{{{item.mitigations}}}}
+ {{item:call:getFindingMitigations}}
References
- {{{{item.references}}}}
-
+ {{item:call:getFindingReferences}}
}}
-}}
}
-## Data Flows
+
+## Data Flows
{dataflows:repeat:
Name|{{item.name}}
@@ -136,50 +134,51 @@ Is Response|{{item.isResponse}}|
In Scope|{{item.inScope}}|
Finding Count|{{item:call:getFindingCount}}|
-{{item.findings:if:
-
+{{item:call:getInScopeFindings:
**Threats**
-{{item.findings:repeat:
- {{{{item.id}}}} -- {{{{item.threat_id}}}} -- {{{{item.description}}}}
- Targeted Element
- {{{{item.target}}}}
- Severity
- {{{{item.severity}}}}
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
+ Targeted Element
+ {{item:call:getFindingTarget}}
+ Severity
+ {{item:call:getFindingSeverity}}
Example Instances
- {{{{item.example}}}}
+ {{item:call:getFindingExample}}
Mitigations
- {{{{item.mitigations}}}}
+ {{item:call:getFindingMitigations}}
References
- {{{{item.references}}}}
-
+ {{item:call:getFindingReferences}}
}}
-}}
}
+
{tm.excluded_findings:if:
# Excluded Threats
}
{tm.excluded_findings:repeat:
- {{item.id}} -- {{item.threat_id}} -- {{item.description}}
- **{{item.threat_id}}** was excluded for **{{item.target}}** because of the assumption: "{{item.assumption.name}}
-"
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
+
+ {{item:call:getThreatId}} was excluded for
+ {{item:call:getFindingTarget}}
+ because of the assumption "{{item.assumption.name}}"
+
{{item.assumption.description:if:
- Assumption description
- {{item.assumption.description}}
+ Assumption description
+ {{item.assumption.description}}
}}
-
- Targeted Element
- {{item.target}}
- Severity
- {{item.severity}}
+ Severity
+ {{item:call:getFindingSeverity}}
Example Instances
- {{item.example}}
+ {{item:call:getFindingExample}}
References
- {{item.references}}
+ {{item:call:getFindingReferences}}
}
diff --git a/docs/basic_template.md b/docs/basic_template.md
index 451711b4..31c30a66 100644
--- a/docs/basic_template.md
+++ b/docs/basic_template.md
@@ -49,21 +49,29 @@ Name|Description|Classification
-|{findings:repeat:
+{findings:repeat:
- {{item.threat_id}} -- {{item.description}}
- Targeted Element
- {{item.target}}
- Severity
- {{item.severity}}
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
+
+ Targeted Element
+ {{item:call:getFindingTarget}}
+
+ Severity
+ {{item:call:getFindingSeverity}}
+
Example Instances
- {{item.example}}
+ {{item:call:getFindingExample}}
+
Mitigations
- {{item.mitigations}}
+ {{item:call:getFindingMitigations}}
+
References
- {{item.references}}
-
+ {{item:call:getFindingReferences}}
+
-
-}|
+}||
+
+
diff --git a/docs/reveal.md b/docs/reveal.md
index 4fb4c162..61a9c876 100644
--- a/docs/reveal.md
+++ b/docs/reveal.md
@@ -46,7 +46,6 @@
----
}
-
---
## Actors
@@ -59,29 +58,25 @@
- **is Admin** : {{item.isAdmin}}
- **# of findings** : {{item:call:getFindingCount}}
-{{item.findings:not:
----
-}}
-
-{{item.findings:if:
+{{item:call:getInScopeFindings:
----
**Findings**
----
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
-{{item.findings:repeat:
- {{{{item.id}}}} -- {{{{item.description}}}}
-
- - **Targeted Element** : {{{{item.target}}}}
- - **Severity** : {{{{item.severity}}}}
- - **References** : {{{{item.references}}}}
+ - **Targeted Element** : {{item:call:getFindingTarget}}
+ - **Severity** : {{item:call:getFindingSeverity}}
+ - **References** : {{item:call:getFindingReferences}}
----
-
-}}
}}
}
+---
+
## Trust Boundaries
----
@@ -90,33 +85,32 @@
- **name** : {{item.name}}
- **description** : {{item.description}}
- **in scope** : {{item.inScope}}
-- **immediate parent** : {{item.parents:if:{{item:call:getParentName}}}}{{item.parents:not:N/A, primary boundary}}
+- **immediate parent** :
+ {{item.parents:if:{{item:call:getParentName}}}}
+ {{item.parents:not:N/A, primary boundary}}
- **all parents** : {{item.parents:call:{{{{item.display_name:call:}}}}, }}
- **classification** : {{item.maxClassification}}
- **finding count** : {{item:call:getFindingCount}}
-{{item.findings:not:
----
-}}
-
-{{item.findings:if:
+{{item:call:getInScopeFindings:
----
**Findings**
----
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
-{{item.findings:repeat:
- {{{{item.id}}}} - {{{{item.description}}}}
+ - **Targeted Element** : {{item:call:getFindingTarget}}
+ - **Severity** : {{item:call:getFindingSeverity}}
+ - **References** : {{item:call:getFindingReferences}}
- - **Targeted Element** : {{{{item.target}}}}
- - **Severity** : {{{{item.severity}}}}
- - **References** : {{{{item.references}}}}
----
-
-}}
}}
}
+---
+
## Assets
{assets:repeat:
@@ -127,59 +121,49 @@
- **type** : {{item:call:getElementType}}
- **# of findings** : {{item:call:getFindingCount}}
-{{item.findings:not:
----
-}}
-
-{{item.findings:if:
+{{item:call:getInScopeFindings:
----
**Findings**
----
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
-{{item.findings:repeat:
- {{{{item.id}}}} - {{{{item.description}}}}
+ - **Targeted Element** : {{item:call:getFindingTarget}}
+ - **Severity** : {{item:call:getFindingSeverity}}
+ - **References** : {{item:call:getFindingReferences}}
- - **Targeted Element** : {{{{item.target}}}}
- - **Severity** : {{{{item.severity}}}}
- - **References** : {{{{item.references}}}}
----
-
-}}
}}
}
+---
+
## Data Flows
{dataflows:repeat:
-Name|{{item.name}}
-|:----|:----|
-Description|{{item.description}}|
-Sink|{{item.sink}}|
-Source|{{item.source}}|
-Is Response|{{item.isResponse}}|
-In Scope|{{item.inScope}}|
-Finding Count|{{item:call:getFindingCount}}|
-
-{{item.findings:not:
----
-}}
+- **name** : {{item.name}}
+- **description** : {{item.description}}
+- **sink** : {{item.sink}}
+- **source** : {{item.source}}
+- **is response** : {{item.isResponse}}
+- **in scope** : {{item.inScope}}
+- **finding count** : {{item:call:getFindingCount}}
-{{item.findings:if:
+{{item:call:getInScopeFindings:
----
**Findings**
----
+
+ {{item:call:getThreatId}} — {{item:call:getFindingDescription}}
+
-{{item.findings:repeat:
- {{{{item.id}}}} - {{{{item.description}}}}
+ - **Targeted Element** : {{item:call:getFindingTarget}}
+ - **Severity** : {{item:call:getFindingSeverity}}
+ - **References** : {{item:call:getFindingReferences}}
- - **Targeted Element** : {{{{item.target}}}}
- - **Severity** : {{{{item.severity}}}}
- - **References** : {{{{item.references}}}}
----
-
-}}
}}
}
-
diff --git a/pytm/report_util.py b/pytm/report_util.py
index 90df7de6..97b1322b 100644
--- a/pytm/report_util.py
+++ b/pytm/report_util.py
@@ -21,14 +21,40 @@ def getNamesOfParents(element):
return parents
else:
return "ERROR: getNamesOfParents method is not valid for " + element.__class__.__name__
+
+
+ @staticmethod
+ def getInScopeFindings(element):
+ """
+ Return only findings that:
+ 1. Belong to an in-scope element
+ 2. Target an in-scope element
+ """
+ from pytm import Element
+
+ if not isinstance(element, Element):
+ return []
+
+ if not element.inScope:
+ return []
+
+ in_scope_findings = []
+
+ for finding in element.findings:
+ target = getattr(finding, "target", None)
+ if target is not None and getattr(target, "inScope", False):
+ in_scope_findings.append(finding)
+
+ return in_scope_findings
+
@staticmethod
def getFindingCount(element):
from pytm import Element
- if (isinstance(element, Element)):
- return str(len(list(element.findings)))
- else:
+ if not isinstance(element, Element):
return "ERROR: getFindingCount method is not valid for " + element.__class__.__name__
+ return str(len(ReportUtils.getInScopeFindings(element)))
+
@staticmethod
def getElementType(element):
@@ -37,3 +63,53 @@ def getElementType(element):
return str(element.__class__.__name__)
else:
return "ERROR: getElementType method is not valid for " + element.__class__.__name__
+
+
+ @staticmethod
+ def getThreatId(obj):
+ from pytm import Finding
+ if isinstance(obj, Finding):
+ return obj.threat_id
+ return ""
+
+ @staticmethod
+ def getFindingDescription(obj):
+ from pytm import Finding
+ if isinstance(obj, Finding):
+ return obj.description
+ return ""
+
+ @staticmethod
+ def getFindingTarget(obj):
+ from pytm import Finding
+ if isinstance(obj, Finding):
+ return obj.target
+ return ""
+
+ @staticmethod
+ def getFindingSeverity(obj):
+ from pytm import Finding
+ if isinstance(obj, Finding):
+ return obj.severity
+ return ""
+
+ @staticmethod
+ def getFindingMitigations(obj):
+ from pytm import Finding
+ if isinstance(obj, Finding):
+ return obj.mitigations
+ return ""
+
+ @staticmethod
+ def getFindingReferences(obj):
+ from pytm import Finding
+ if isinstance(obj, Finding):
+ return obj.references
+ return ""
+
+ @staticmethod
+ def getFindingExample(obj):
+ from pytm import Finding
+ if isinstance(obj, Finding):
+ return obj.example
+ return ""