Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Goal
<!-- Briefly describe what this PR accomplishes -->

## Changes
<!-- List main changes (files, behavior) -->

## Testing
<!-- How was this tested? (manual steps, commands, automated tests) -->

## Artifacts & Screenshots
<!-- Attach screenshots, logs, or link to artifacts if applicable -->

---

### Checklist
- [ ] PR title is clear and descriptive
- [ ] Documentation updated if needed
- [ ] No secrets or large temporary files committed
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store

# Keep local cosign key material out of version control.
labs/lab8/signing/cosign.key
labs/lab8/signing/cosign.pub
labs/lab8/bin/cosign
Binary file added labs/devsec3-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions labs/lab10/imports/import-grype-vuln-results.json.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"minimum_severity":"Info","active":false,"verified":false,"endpoint_to_add":null,"product_type_name":"Engineering","product_name":"Juice Shop","engagement_name":"Labs Security Testing","auto_create_context":true,"deduplication_on_engagement":false,"lead":null,"push_to_jira":false,"api_scan_configuration":null,"create_finding_groups_for_all_findings":true,"test_id":7,"engagement_id":4,"product_id":4,"product_type_id":3,"statistics":{"after":{"info":{"active":12,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":12},"low":{"active":3,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":3},"medium":{"active":32,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":32},"high":{"active":64,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":64},"critical":{"active":11,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":11},"total":{"active":122,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":122}}},"apply_tags_to_findings":false,"apply_tags_to_endpoints":false,"scan_type":"Anchore Grype","close_old_findings":false,"close_old_findings_product_scope":false,"test":7}
1 change: 1 addition & 0 deletions labs/lab10/imports/import-semgrep-results.json.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"minimum_severity":"Info","active":false,"verified":false,"endpoint_to_add":null,"product_type_name":"Engineering","product_name":"Juice Shop","engagement_name":"Labs Security Testing","auto_create_context":true,"deduplication_on_engagement":false,"lead":null,"push_to_jira":false,"api_scan_configuration":null,"create_finding_groups_for_all_findings":true,"test_id":5,"engagement_id":4,"product_id":4,"product_type_id":3,"statistics":{"after":{"info":{"active":0,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":0},"low":{"active":0,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":0},"medium":{"active":18,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":18},"high":{"active":7,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":7},"critical":{"active":0,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":0},"total":{"active":25,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":25}}},"pro":["Did you know, Pro has an automated no-code connector for Semgrep JSON Report? Try today for free or email us at hello@defectdojo.com"],"apply_tags_to_findings":false,"apply_tags_to_endpoints":false,"scan_type":"Semgrep JSON Report","close_old_findings":false,"close_old_findings_product_scope":false,"test":5}
1 change: 1 addition & 0 deletions labs/lab10/imports/import-trivy-vuln-detailed.json.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"minimum_severity":"Info","active":false,"verified":false,"endpoint_to_add":null,"product_type_name":"Engineering","product_name":"Juice Shop","engagement_name":"Labs Security Testing","auto_create_context":true,"deduplication_on_engagement":false,"lead":null,"push_to_jira":false,"api_scan_configuration":null,"create_finding_groups_for_all_findings":true,"test_id":6,"engagement_id":4,"product_id":4,"product_type_id":3,"statistics":{"after":{"info":{"active":0,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":0},"low":{"active":18,"verified":18,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":18},"medium":{"active":36,"verified":34,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":36},"high":{"active":83,"verified":81,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":83},"critical":{"active":10,"verified":10,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":10},"total":{"active":147,"verified":143,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":147}}},"apply_tags_to_findings":false,"apply_tags_to_endpoints":false,"scan_type":"Trivy Scan","close_old_findings":false,"close_old_findings_product_scope":false,"test":6}
1 change: 1 addition & 0 deletions labs/lab10/imports/import-zap-report-noauth.xml.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"minimum_severity":"Info","active":false,"verified":false,"endpoint_to_add":null,"product_type_name":"Engineering","product_name":"Juice Shop","engagement_name":"Labs Security Testing","auto_create_context":true,"deduplication_on_engagement":false,"lead":null,"push_to_jira":false,"api_scan_configuration":null,"create_finding_groups_for_all_findings":true,"test_id":8,"engagement_id":4,"product_id":4,"product_type_id":3,"statistics":{"after":{"info":{"active":4,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":4},"low":{"active":6,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":6},"medium":{"active":2,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":2},"high":{"active":0,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":0},"critical":{"active":0,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":0},"total":{"active":12,"verified":0,"duplicate":0,"false_p":0,"out_of_scope":0,"is_mitigated":0,"risk_accepted":0,"total":12}}},"apply_tags_to_findings":false,"apply_tags_to_endpoints":false,"scan_type":"ZAP Scan","close_old_findings":false,"close_old_findings_product_scope":false,"test":8}
5 changes: 5 additions & 0 deletions labs/lab10/imports/nuclei-status.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Nuclei import status for Lab 10

- Expected input path from lab: labs/lab5/nuclei/nuclei-results.json
- Status on 2026-04-13: source report not present in this repository
- Result: Nuclei import was skipped intentionally because there was no input artifact to import
100 changes: 99 additions & 1 deletion labs/lab10/imports/run-imports.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@ SCAN_NUCLEI="${SCAN_NUCLEI:-}"

if $have_jq; then
echo "Discovering importer names from /test_types/ ..."
mapfile -t types < <(curl -sS -H "Authorization: Token $DD_TOKEN" "$DD_API/test_types/?limit=2000" | jq -r '.results[].name')
types=()
while IFS= read -r type_name; do
types+=("$type_name")
done < <(curl -sS -H "Authorization: Token $DD_TOKEN" "$DD_API/test_types/?limit=2000" | jq -r '.results[].name')
choose_type() {
local pat="$1"
local fallback="$2"
Expand Down Expand Up @@ -89,13 +92,108 @@ echo " Trivy = $SCAN_TRIVY"
echo " Nuclei = $SCAN_NUCLEI"
echo " Grype = $SCAN_GRYPE"

convert_zap_json_to_xml() {
local input_file="$1"
local output_file="$2"

python3 - "$input_file" "$output_file" <<'PY'
import json
import sys
import xml.etree.ElementTree as ET

input_file, output_file = sys.argv[1], sys.argv[2]

with open(input_file, "r", encoding="utf-8") as fh:
report = json.load(fh)

root = ET.Element(
"OWASPZAPReport",
{
"version": report.get("@version", ""),
"generated": report.get("@generated", ""),
},
)

for site in report.get("site", []):
site_elem = ET.SubElement(
root,
"site",
{
"name": site.get("@name", ""),
"host": site.get("@host", ""),
"port": str(site.get("@port", "")),
"ssl": str(site.get("@ssl", "")),
},
)
alerts_elem = ET.SubElement(site_elem, "alerts")
for alert in site.get("alerts", []):
alert_elem = ET.SubElement(alerts_elem, "alertitem")
for field in (
"pluginid",
"alertRef",
"alert",
"name",
"riskcode",
"confidence",
"riskdesc",
"desc",
):
value = alert.get(field, "")
if value is not None:
ET.SubElement(alert_elem, field).text = str(value)

instances_elem = ET.SubElement(alert_elem, "instances")
for instance in alert.get("instances", []):
instance_elem = ET.SubElement(instances_elem, "instance")
for field in (
"id",
"uri",
"nodeName",
"method",
"param",
"attack",
"evidence",
"otherinfo",
"requestheader",
"requestbody",
"responseheader",
"responsebody",
):
value = instance.get(field, "")
if value is not None:
ET.SubElement(instance_elem, field).text = str(value)

for field in (
"count",
"solution",
"otherinfo",
"reference",
"cweid",
"wascid",
"sourceid",
):
value = alert.get(field, "")
if value is not None:
ET.SubElement(alert_elem, field).text = str(value)

tree = ET.ElementTree(root)
tree.write(output_file, encoding="utf-8", xml_declaration=True)
PY
}

import_scan() {
local scan_type="$1"; shift
local file="$1"; shift
if [[ ! -f "$file" ]]; then
echo "SKIP: $scan_type file not found: $file"
return 0
fi
if [[ "$scan_type" == "$SCAN_ZAP" && "$file" == *.json ]]; then
local converted_file="$out_dir/$(basename "${file%.json}").xml"
echo "Converting ZAP JSON report to XML: $converted_file"
convert_zap_json_to_xml "$file" "$converted_file"
file="$converted_file"
fi
local base out
base="$(basename "$file")"
out="$out_dir/import-${base//[^A-Za-z0-9_.-]/_}.json"
Expand Down
2 changes: 2 additions & 0 deletions labs/lab10/imports/zap-report-noauth.xml

Large diffs are not rendered by default.

Loading