Skip to content

Commit 61c8bb2

Browse files
authored
Merge branch 'dev' into performance-test-v3-updates
2 parents 7ab88df + d698147 commit 61c8bb2

24 files changed

Lines changed: 4766 additions & 4398 deletions

.github/workflows/build-docker-images-for-testing.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353

5454
- name: Build
5555
id: docker_build
56-
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
56+
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
5757
timeout-minutes: 15
5858
env:
5959
DOCKER_BUILD_CHECKS_ANNOTATIONS: false

.github/workflows/release-x-manual-docker-containers.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
# we cannot set any tags here, those are set on the merged digest in release-x-manual-merge-container-digests.yml
7070
- name: Build and push images
7171
id: build
72-
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
72+
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
7373
env:
7474
DOCKER_BUILD_CHECKS_ANNOTATIONS: false
7575
with:

Dockerfile.django-alpine

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ COPY \
7878
docker/reach_broker.sh \
7979
docker/certs/* \
8080
/
81-
COPY wsgi.py manage.py ./
81+
COPY manage.py ./
8282
COPY dojo/ ./dojo/
8383

8484
# Add extra fixtures to docker image which are loaded by the initializer

Dockerfile.django-debian

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ COPY \
8181
docker/reach_broker.sh \
8282
docker/certs/* \
8383
/
84-
COPY wsgi.py manage.py ./
84+
COPY manage.py ./
8585
COPY dojo/ ./dojo/
8686

8787
# Add extra fixtures to docker image which are loaded by the initializer

components/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
"metismenu": "~3.0.7",
3434
"moment": "^2.30.1",
3535
"morris.js": "morrisjs/morris.js",
36-
"pdfmake": "^0.3.5",
36+
"pdfmake": "^0.3.6",
3737
"startbootstrap-sb-admin-2": "1.0.7"
3838
},
3939
"engines": {

components/yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,10 @@ pdfkit@^0.17.2:
385385
linebreak "^1.1.0"
386386
png-js "^1.0.0"
387387

388-
pdfmake@^0.3.5:
389-
version "0.3.5"
390-
resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.3.5.tgz#74ebca563b3fd5bf8a50104bc702e42dd63ffae5"
391-
integrity sha512-DR7jRrK4lk7UiRT6pi+NeWhW1ToTsL2Y8CH+bFKNYz3M7agIVgeCtwARveEORhCAqoG3AUDrN318xU/lkOr1Bg==
388+
pdfmake@^0.3.6:
389+
version "0.3.6"
390+
resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.3.6.tgz#8c149872d12e9ebbcced762250a941fea189e040"
391+
integrity sha512-c3uVTdwaNqE/Qaum8BTi9StbFyrYunaR+c94kA6vZA5eHuLFSnvw3pK6Y/0OU4xTFbjKsaHwdeAJinV9ci+OcQ==
392392
dependencies:
393393
linebreak "^1.1.0"
394394
pdfkit "^0.17.2"
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
title: "IriusRisk Threats Scan"
3+
toc_hide: true
4+
---
5+
6+
The [IriusRisk](https://www.iriusrisk.com/) parser for DefectDojo supports imports from CSV format. This document details the parsing of IriusRisk threat model CSV exports into DefectDojo field mappings, unmapped fields, and transformation notes for easier troubleshooting and analysis.
7+
8+
## Supported File Types
9+
10+
The IriusRisk parser accepts CSV file format. To generate this file from IriusRisk:
11+
12+
1. Log into your IriusRisk console
13+
2. Navigate to the project containing your threat model
14+
3. Export the threats as CSV
15+
4. Save the file with a `.csv` extension
16+
5. Upload to DefectDojo using the "IriusRisk Threats Scan" scan type
17+
18+
## Default Deduplication Hashcode Fields
19+
20+
DefectDojo identifies duplicate Findings using these [hashcode fields](https://docs.defectdojo.com/en/working_with_findings/finding_deduplication/about_deduplication/):
21+
22+
- title
23+
- component_name
24+
25+
### Sample Scan Data
26+
27+
Sample IriusRisk scans can be found in the [sample scan data folder](https://github.com/DefectDojo/django-DefectDojo/tree/master/unittests/scans/iriusrisk).
28+
29+
## Link To Tool
30+
31+
- [IriusRisk](https://www.iriusrisk.com/)
32+
- [IriusRisk Documentation](https://support.iriusrisk.com/)
33+
34+
## CSV Format (Threat Model Export)
35+
36+
### Total Fields in CSV
37+
38+
- Total data fields: 14
39+
- Total data fields parsed: 14
40+
- Total data fields NOT parsed: 0
41+
42+
### CSV Format Field Mapping Details
43+
44+
<details>
45+
<summary>Click to expand Field Mapping Table</summary>
46+
47+
| Source Field | DefectDojo Field | Notes |
48+
| ------------------------ | -------------------- | --------------------------------------------------------------------- |
49+
| Threat | title | Truncated to 500 characters with "..." suffix if longer |
50+
| Current Risk | severity | Mapped from IriusRisk risk levels to DefectDojo severity levels |
51+
| Component | component_name | The affected asset or component from the threat model |
52+
| Threat | description | Full threat text included as first line of structured description |
53+
| Component | description | Included in structured description block |
54+
| Use case | description | Threat category included in structured description |
55+
| Source | description | Origin of the threat included in structured description |
56+
| Inherent Risk | description | Pre-control risk level included in structured description |
57+
| Current Risk | description | Current risk level included in structured description |
58+
| Projected Risk | description | Post-mitigation risk level included in structured description |
59+
| Countermeasure progress | description | Percentage complete included in structured description |
60+
| Weakness tests | description | Test status included in structured description |
61+
| Countermeasure tests | description | Test status included in structured description |
62+
| Owner | description | Conditionally appended to description only when present |
63+
| STRIDE-LM | description | Conditionally appended to description only when present |
64+
| Risk Response | mitigation | Mitigation status percentages from IriusRisk |
65+
| MITRE reference | cwe | When value matches CWE-NNN pattern, integer is extracted to cwe field |
66+
| MITRE reference | references | When value does not match CWE pattern, stored as references |
67+
68+
</details>
69+
70+
### Additional Finding Field Settings (CSV Format)
71+
72+
<details>
73+
<summary>Click to expand Additional Settings Table</summary>
74+
75+
| Finding Field | Default Value | Notes |
76+
| ---------------- | -------------------------------- | ----------------------------------------------------------- |
77+
| static_finding | False | Threat model data is neither static nor dynamic analysis |
78+
| dynamic_finding | False | Threat model data is neither static nor dynamic analysis |
79+
| active | True (False when "Very low") | Set to False when Current Risk is "Very low" (fully mitigated) |
80+
81+
</details>
82+
83+
## Special Processing Notes
84+
85+
### Status Conversion
86+
87+
IriusRisk uses a five-level risk scale that is mapped to DefectDojo severity levels:
88+
89+
- `Critical` → Critical
90+
- `High` → High
91+
- `Medium` → Medium
92+
- `Low` → Low
93+
- `Very low` → Info
94+
95+
Any unrecognized risk value defaults to Info. The mapping uses the "Current Risk" column, which reflects the risk level accounting for existing controls and represents the most accurate current exposure.
96+
97+
### Title Format
98+
99+
Finding titles are derived from the "Threat" column. Threat descriptions longer than 500 characters are truncated to 497 characters with a "..." suffix appended. Shorter threat texts are used as-is without modification.
100+
101+
### Description Construction
102+
103+
The parser constructs a structured markdown description containing all relevant CSV fields:
104+
105+
1. Full threat text (untruncated, regardless of title truncation)
106+
2. Component name
107+
3. Use case (threat category, e.g., "Elevation of Privilege", "Networking")
108+
4. Source (e.g., "Created by Rules Engine")
109+
5. Inherent Risk (pre-control risk level)
110+
6. Current Risk (risk with existing controls)
111+
7. Projected Risk (risk after planned mitigations)
112+
8. Countermeasure Progress (percentage complete)
113+
9. Weakness Tests (test status)
114+
10. Countermeasure Tests (test status)
115+
11. Owner (conditionally included only when the field contains a value)
116+
12. STRIDE-LM (conditionally included only when the field contains a value)
117+
118+
Each field is formatted as a bold markdown label followed by the value, with fields separated by newlines.
119+
120+
### MITRE Reference / CWE Extraction
121+
122+
The parser reads the "MITRE reference" column and applies conditional mapping:
123+
124+
- If the value matches the pattern `CWE-NNN` (e.g., "CWE-284"), the integer portion is extracted and set on the finding's `cwe` field.
125+
- If the value is present but does not match the CWE pattern (e.g., "T1059" for a MITRE ATT&CK technique), the full value is stored in the finding's `references` field.
126+
- If the column is empty, neither field is set.
127+
128+
### Mitigation Construction
129+
130+
The mitigation field is populated directly from the "Risk Response" column, which contains the IriusRisk mitigation status in the format: "Planned mitigation: X%. Mitigated: Y%. Unmitigated: Z%." This preserves the original IriusRisk mitigation tracking percentages.
131+
132+
### Active/Inactive Logic
133+
134+
Findings are set to active by default. When the "Current Risk" value is "Very low", the finding is set to inactive, as this indicates the threat has been fully mitigated through implemented countermeasures.
135+
136+
### Deduplication
137+
138+
Deduplication uses DefectDojo's hashcode algorithm with the title and component_name fields to identify duplicate findings. These stable fields ensure that reimports correctly match existing findings even when risk levels or countermeasure progress change between scans.
139+
140+
### Duplicate Rows in Source Data
141+
142+
IriusRisk CSV exports can contain multiple rows with the same Component and Threat but different Risk Response values. These represent distinct countermeasure paths for the same threat. Each row is imported as a separate finding, distinguished by its description content which incorporates all CSV fields.

dojo/api_v2/views.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,13 +777,17 @@ def download_proof(self, request, pk=None):
777777
)
778778
# Get the path of the file in media root
779779
file_path = Path(settings.MEDIA_ROOT) / file_object.name
780+
# NOTE: FileResponse takes ownership of closing the file handle when the response is closed.
781+
# Explicitly register the closer to avoid potential resource leaks and satisfy static analyzers.
780782
file_handle = file_path.open("rb")
781783
# send file
782784
response = FileResponse(
783785
file_handle,
784786
content_type=mimetypes.guess_type(str(file_path))[0] or "application/octet-stream",
785787
status=status.HTTP_200_OK,
786788
)
789+
if hasattr(response, "_resource_closers"):
790+
response._resource_closers.append(file_handle.close)
787791
response["Content-Length"] = file_object.size
788792
response[
789793
"Content-Disposition"

dojo/engagement/views.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,9 +1578,10 @@ def download_risk_acceptance(request, eid, raid):
15781578
# Ensure the risk acceptance is under the supplied engagement
15791579
if not Engagement.objects.filter(risk_acceptance=risk_acceptance, id=eid).exists():
15801580
raise PermissionDenied
1581-
response = StreamingHttpResponse(
1582-
FileIterWrapper(
1583-
(Path(settings.MEDIA_ROOT) / "risk_acceptance.path.name").open(mode="rb")))
1581+
file_handle = (Path(settings.MEDIA_ROOT) / "risk_acceptance.path.name").open(mode="rb")
1582+
response = StreamingHttpResponse(FileIterWrapper(file_handle))
1583+
if hasattr(response, "_resource_closers"):
1584+
response._resource_closers.append(file_handle.close)
15841585
response["Content-Disposition"] = f'attachment; filename="{risk_acceptance.filename()}"'
15851586
mimetype, _encoding = mimetypes.guess_type(risk_acceptance.path.name)
15861587
response["Content-Type"] = mimetype or "application/octet-stream"

0 commit comments

Comments
 (0)