diff --git a/labs/lab2/baseline/data-asset-diagram.png b/labs/lab2/baseline/data-asset-diagram.png
new file mode 100644
index 00000000..4457d768
Binary files /dev/null and b/labs/lab2/baseline/data-asset-diagram.png differ
diff --git a/labs/lab2/baseline/data-flow-diagram.png b/labs/lab2/baseline/data-flow-diagram.png
new file mode 100644
index 00000000..a8803816
Binary files /dev/null and b/labs/lab2/baseline/data-flow-diagram.png differ
diff --git a/labs/lab2/baseline/report.pdf b/labs/lab2/baseline/report.pdf
new file mode 100644
index 00000000..3b6c09b4
Binary files /dev/null and b/labs/lab2/baseline/report.pdf differ
diff --git a/labs/lab2/baseline/risks.json b/labs/lab2/baseline/risks.json
new file mode 100644
index 00000000..05c41156
--- /dev/null
+++ b/labs/lab2/baseline/risks.json
@@ -0,0 +1,410 @@
+[
+ {
+ "category": "unnecessary-data-transfer",
+ "risk_status": "unchecked",
+ "severity": "low",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "low",
+ "title": "Unnecessary Data Transfer of Tokens & Sessions data at User Browser from/to Juice Shop Application",
+ "synthetic_id": "unnecessary-data-transfer@tokens-sessions@user-browser@juice-shop",
+ "most_relevant_data_asset": "tokens-sessions",
+ "most_relevant_technical_asset": "user-browser",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "user-browser"
+ ]
+ },
+ {
+ "category": "unnecessary-data-transfer",
+ "risk_status": "unchecked",
+ "severity": "low",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "low",
+ "title": "Unnecessary Data Transfer of Tokens & Sessions data at User Browser from/to Reverse Proxy",
+ "synthetic_id": "unnecessary-data-transfer@tokens-sessions@user-browser@reverse-proxy",
+ "most_relevant_data_asset": "tokens-sessions",
+ "most_relevant_technical_asset": "user-browser",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "user-browser"
+ ]
+ },
+ {
+ "category": "server-side-request-forgery",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "low",
+ "title": "Server-Side Request Forgery (SSRF) risk at Juice Shop Application server-side web-requesting the target Webhook Endpoint via To Challenge WebHook",
+ "synthetic_id": "server-side-request-forgery@juice-shop@webhook-endpoint@juice-shop>to-challenge-webhook",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "juice-shop>to-challenge-webhook",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "server-side-request-forgery",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "low",
+ "title": "Server-Side Request Forgery (SSRF) risk at Reverse Proxy server-side web-requesting the target Juice Shop Application via To App",
+ "synthetic_id": "server-side-request-forgery@reverse-proxy@juice-shop@reverse-proxy>to-app",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "reverse-proxy",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "reverse-proxy>to-app",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "reverse-proxy"
+ ]
+ },
+ {
+ "category": "missing-hardening",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "low",
+ "title": "Missing Hardening risk at Juice Shop Application",
+ "synthetic_id": "missing-hardening@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "missing-hardening",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "low",
+ "title": "Missing Hardening risk at Persistent Storage",
+ "synthetic_id": "missing-hardening@persistent-storage",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "persistent-storage",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "persistent-storage"
+ ]
+ },
+ {
+ "category": "container-baseimage-backdooring",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Container Base Image Backdooring risk at Juice Shop Application",
+ "synthetic_id": "container-baseimage-backdooring@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "probable",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "missing-build-infrastructure",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Missing Build Infrastructure in the threat model (referencing asset Juice Shop Application as an example)",
+ "synthetic_id": "missing-build-infrastructure@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": []
+ },
+ {
+ "category": "missing-authentication",
+ "risk_status": "unchecked",
+ "severity": "elevated",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "medium",
+ "title": "Missing Authentication covering communication link To App from Reverse Proxy to Juice Shop Application",
+ "synthetic_id": "missing-authentication@reverse-proxy>to-app@reverse-proxy@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "reverse-proxy>to-app",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "unnecessary-technical-asset",
+ "risk_status": "unchecked",
+ "severity": "low",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "low",
+ "title": "Unnecessary Technical Asset named Persistent Storage",
+ "synthetic_id": "unnecessary-technical-asset@persistent-storage",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "persistent-storage",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "persistent-storage"
+ ]
+ },
+ {
+ "category": "unnecessary-technical-asset",
+ "risk_status": "unchecked",
+ "severity": "low",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "low",
+ "title": "Unnecessary Technical Asset named User Browser",
+ "synthetic_id": "unnecessary-technical-asset@user-browser",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "user-browser",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "user-browser"
+ ]
+ },
+ {
+ "category": "unencrypted-asset",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Unencrypted Technical Asset named Juice Shop Application",
+ "synthetic_id": "unencrypted-asset@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "unencrypted-asset",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Unencrypted Technical Asset named Persistent Storage",
+ "synthetic_id": "unencrypted-asset@persistent-storage",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "persistent-storage",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "persistent-storage"
+ ]
+ },
+ {
+ "category": "missing-authentication-second-factor",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Missing Two-Factor Authentication covering communication link Direct to App (no proxy) from User Browser to Juice Shop Application",
+ "synthetic_id": "missing-authentication-second-factor@user-browser>direct-to-app-no-proxy@user-browser@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "user-browser>direct-to-app-no-proxy",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "missing-authentication-second-factor",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Missing Two-Factor Authentication covering communication link To App from User Browser forwarded via Reverse Proxy to Juice Shop Application",
+ "synthetic_id": "missing-authentication-second-factor@reverse-proxy>to-app@reverse-proxy@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "reverse-proxy>to-app",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "missing-vault",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Missing Vault (Secret Storage) in the threat model (referencing asset Juice Shop Application as an example)",
+ "synthetic_id": "missing-vault@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": []
+ },
+ {
+ "category": "missing-waf",
+ "risk_status": "unchecked",
+ "severity": "low",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "low",
+ "title": "Missing Web Application Firewall (WAF) risk at Juice Shop Application",
+ "synthetic_id": "missing-waf@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "unencrypted-communication",
+ "risk_status": "unchecked",
+ "severity": "elevated",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "high",
+ "title": "Unencrypted Communication named Direct to App (no proxy) between User Browser and Juice Shop Application transferring authentication data (like credentials, token, session-id, etc.)",
+ "synthetic_id": "unencrypted-communication@user-browser>direct-to-app-no-proxy@user-browser@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "user-browser",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "user-browser>direct-to-app-no-proxy",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "unencrypted-communication",
+ "risk_status": "unchecked",
+ "severity": "elevated",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "medium",
+ "title": "Unencrypted Communication named To App between Reverse Proxy and Juice Shop Application",
+ "synthetic_id": "unencrypted-communication@reverse-proxy>to-app@reverse-proxy@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "reverse-proxy",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "reverse-proxy>to-app",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "missing-identity-store",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "unlikely",
+ "exploitation_impact": "medium",
+ "title": "Missing Identity Store in the threat model (referencing asset Reverse Proxy as an example)",
+ "synthetic_id": "missing-identity-store@reverse-proxy",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "reverse-proxy",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": []
+ },
+ {
+ "category": "cross-site-scripting",
+ "risk_status": "unchecked",
+ "severity": "elevated",
+ "exploitation_likelihood": "likely",
+ "exploitation_impact": "medium",
+ "title": "Cross-Site Scripting (XSS) risk at Juice Shop Application",
+ "synthetic_id": "cross-site-scripting@juice-shop",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "",
+ "data_breach_probability": "possible",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "cross-site-request-forgery",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "very-likely",
+ "exploitation_impact": "low",
+ "title": "Cross-Site Request Forgery (CSRF) risk at Juice Shop Application via Direct to App (no proxy) from User Browser",
+ "synthetic_id": "cross-site-request-forgery@juice-shop@user-browser>direct-to-app-no-proxy",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "user-browser>direct-to-app-no-proxy",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ },
+ {
+ "category": "cross-site-request-forgery",
+ "risk_status": "unchecked",
+ "severity": "medium",
+ "exploitation_likelihood": "very-likely",
+ "exploitation_impact": "low",
+ "title": "Cross-Site Request Forgery (CSRF) risk at Juice Shop Application via To App from Reverse Proxy",
+ "synthetic_id": "cross-site-request-forgery@juice-shop@reverse-proxy>to-app",
+ "most_relevant_data_asset": "",
+ "most_relevant_technical_asset": "juice-shop",
+ "most_relevant_trust_boundary": "",
+ "most_relevant_shared_runtime": "",
+ "most_relevant_communication_link": "reverse-proxy>to-app",
+ "data_breach_probability": "improbable",
+ "data_breach_technical_assets": [
+ "juice-shop"
+ ]
+ }
+]
\ No newline at end of file
diff --git a/labs/lab2/baseline/stats.json b/labs/lab2/baseline/stats.json
new file mode 100644
index 00000000..88cd78be
--- /dev/null
+++ b/labs/lab2/baseline/stats.json
@@ -0,0 +1 @@
+{"risks":{"critical":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"elevated":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":4},"high":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"low":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":5},"medium":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":14}}}
\ No newline at end of file
diff --git a/labs/lab2/baseline/technical-assets.json b/labs/lab2/baseline/technical-assets.json
new file mode 100644
index 00000000..45457f1e
--- /dev/null
+++ b/labs/lab2/baseline/technical-assets.json
@@ -0,0 +1 @@
+{"juice-shop":{"Id":"juice-shop","Title":"Juice Shop Application","Description":"OWASP Juice Shop server (Node.js/Express, v19.0.0).","Usage":0,"Type":1,"Size":2,"Technology":6,"Machine":2,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":true,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"In-scope web application (contains all business logic and vulnerabilities by design).","Tags":["app","nodejs"],"DataAssetsProcessed":["user-accounts","orders","product-catalog","tokens-sessions"],"DataAssetsStored":["logs"],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"juice-shop\u003eto-challenge-webhook","SourceId":"juice-shop","TargetId":"webhook-endpoint","Title":"To Challenge WebHook","Description":"Optional outbound callback (HTTP POST) to external WebHook when a challenge is solved.","Protocol":2,"Tags":["egress"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["orders"],"DataAssetsReceived":null,"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":70.02881844380403},"persistent-storage":{"Id":"persistent-storage","Title":"Persistent Storage","Description":"Host-mounted volume for database, file uploads, and logs.","Usage":1,"Type":2,"Size":3,"Technology":10,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Local disk storage for the container – not directly exposed, but if compromised it contains sensitive data (database and logs).","Tags":["storage","volume"],"DataAssetsProcessed":[],"DataAssetsStored":["logs","user-accounts","orders","product-catalog"],"DataFormatsAccepted":[3],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":100},"reverse-proxy":{"Id":"reverse-proxy","Title":"Reverse Proxy","Description":"Optional reverse proxy (e.g., Nginx) for TLS termination and adding security headers.","Usage":0,"Type":1,"Size":2,"Technology":20,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":1,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Not exposed to internet directly; improves security of inbound traffic.","Tags":["optional","proxy"],"DataAssetsProcessed":["product-catalog","tokens-sessions"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"reverse-proxy\u003eto-app","SourceId":"reverse-proxy","TargetId":"juice-shop","Title":"To App","Description":"Proxy forwarding to app (HTTP on 3000 internally).","Protocol":1,"Tags":[],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":9.623538157950035},"user-browser":{"Id":"user-browser","Title":"User Browser","Description":"End-user web browser (client).","Usage":0,"Type":0,"Size":0,"Technology":2,"Machine":1,"Internet":true,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":true,"Encryption":0,"JustificationOutOfScope":"","Owner":"External User","Confidentiality":0,"Integrity":1,"Availability":1,"JustificationCiaRating":"Client controlled by end user (potentially an attacker).","Tags":["actor","user"],"DataAssetsProcessed":[],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"user-browser\u003eto-reverse-proxy-preferred","SourceId":"user-browser","TargetId":"reverse-proxy","Title":"To Reverse Proxy (preferred)","Description":"User browser to reverse proxy (HTTPS on 443).","Protocol":2,"Tags":["primary"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true},{"Id":"user-browser\u003edirect-to-app-no-proxy","SourceId":"user-browser","TargetId":"juice-shop","Title":"Direct to App (no proxy)","Description":"Direct browser access to app (HTTP on 3000).","Protocol":1,"Tags":["direct"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":25.859639506459924},"webhook-endpoint":{"Id":"webhook-endpoint","Title":"Webhook Endpoint","Description":"External WebHook service (3rd-party, if configured for integrations).","Usage":0,"Type":0,"Size":0,"Technology":14,"Machine":1,"Internet":true,"MultiTenant":true,"Redundant":true,"CustomDevelopedParts":false,"OutOfScope":true,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"Third-party service to receive notifications (not under our control).","Owner":"Third-Party","Confidentiality":1,"Integrity":1,"Availability":1,"JustificationCiaRating":"External service that receives data (like order or challenge info). Treated as a trusted integration point but could be abused if misconfigured.","Tags":["saas","webhook"],"DataAssetsProcessed":["orders"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":1}}
\ No newline at end of file
diff --git a/labs/lab2/scripts/calculate_risk_score.py b/labs/lab2/scripts/calculate_risk_score.py
new file mode 100644
index 00000000..e3f48666
--- /dev/null
+++ b/labs/lab2/scripts/calculate_risk_score.py
@@ -0,0 +1,30 @@
+import json
+
+# Define the weights
+SEVERITY = {"critical": 5, "elevated": 4, "high": 3, "medium": 2, "low": 1}
+LIKELIHOOD = {"very-likely": 4, "likely": 3, "possible": 2, "unlikely": 1}
+IMPACT = {"high": 3, "medium": 2, "low": 1}
+
+def calculate_score(risk):
+ s = SEVERITY.get(risk.get("severity", "low"), 1)
+ l = LIKELIHOOD.get(risk.get("exploitation_likelihood", "unlikely"), 1)
+ i = IMPACT.get(risk.get("exploitation_impact", "low"), 1)
+
+ return (s * 100) + (l * 10) + i
+
+try:
+ with open("./../baseline/risks.json", "r") as f:
+ risks = json.load(f)
+
+ for r in risks:
+ r["composite_score"] = calculate_score(r)
+ sorted_risks = sorted(risks, key=lambda x: x["composite_score"], reverse=True)
+
+ print("| Score | Severity | Category | Asset | Likelihood | Impact |")
+ print("|---|---|---|---|---|---|")
+
+ for r in sorted_risks[:5]:
+ print(f"| {r['composite_score']} | {r['severity']} | {r['category']} | {r.get('most_relevant_technical_asset', 'N/A')} | {r['exploitation_likelihood']} | {r['exploitation_impact']} |")
+
+except FileNotFoundError:
+ print("Error: not found")
\ No newline at end of file
diff --git a/labs/lab2/secure/data-asset-diagram.png b/labs/lab2/secure/data-asset-diagram.png
new file mode 100644
index 00000000..aacf4016
Binary files /dev/null and b/labs/lab2/secure/data-asset-diagram.png differ
diff --git a/labs/lab2/secure/data-flow-diagram.png b/labs/lab2/secure/data-flow-diagram.png
new file mode 100644
index 00000000..0b4de059
Binary files /dev/null and b/labs/lab2/secure/data-flow-diagram.png differ
diff --git a/labs/lab2/secure/report.pdf b/labs/lab2/secure/report.pdf
new file mode 100644
index 00000000..fd3f58d0
Binary files /dev/null and b/labs/lab2/secure/report.pdf differ
diff --git a/labs/lab2/secure/risks.json b/labs/lab2/secure/risks.json
new file mode 100644
index 00000000..c4bdd9a4
--- /dev/null
+++ b/labs/lab2/secure/risks.json
@@ -0,0 +1 @@
+[{"category":"missing-identity-store","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Identity Store\u003c/b\u003e in the threat model (referencing asset \u003cb\u003eReverse Proxy\u003c/b\u003e as an example)","synthetic_id":"missing-identity-store@reverse-proxy","most_relevant_data_asset":"","most_relevant_technical_asset":"reverse-proxy","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":[]},{"category":"missing-authentication-second-factor","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Two-Factor Authentication\u003c/b\u003e covering communication link \u003cb\u003eDirect to App (no proxy)\u003c/b\u003e from \u003cb\u003eUser Browser\u003c/b\u003e to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-authentication-second-factor@user-browser\u003edirect-to-app-no-proxy@user-browser@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"user-browser\u003edirect-to-app-no-proxy","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"missing-authentication-second-factor","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Two-Factor Authentication\u003c/b\u003e covering communication link \u003cb\u003eTo App\u003c/b\u003e from \u003cb\u003eUser Browser\u003c/b\u003e forwarded via \u003cb\u003eReverse Proxy\u003c/b\u003e to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-authentication-second-factor@reverse-proxy\u003eto-app@reverse-proxy@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"server-side-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eServer-Side Request Forgery (SSRF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e server-side web-requesting the target \u003cb\u003eWebhook Endpoint\u003c/b\u003e via \u003cb\u003eTo Challenge WebHook\u003c/b\u003e","synthetic_id":"server-side-request-forgery@juice-shop@webhook-endpoint@juice-shop\u003eto-challenge-webhook","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"juice-shop\u003eto-challenge-webhook","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"server-side-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eServer-Side Request Forgery (SSRF)\u003c/b\u003e risk at \u003cb\u003eReverse Proxy\u003c/b\u003e server-side web-requesting the target \u003cb\u003eJuice Shop Application\u003c/b\u003e via \u003cb\u003eTo App\u003c/b\u003e","synthetic_id":"server-side-request-forgery@reverse-proxy@juice-shop@reverse-proxy\u003eto-app","most_relevant_data_asset":"","most_relevant_technical_asset":"reverse-proxy","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"possible","data_breach_technical_assets":["reverse-proxy"]},{"category":"missing-authentication","risk_status":"unchecked","severity":"elevated","exploitation_likelihood":"likely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Authentication\u003c/b\u003e covering communication link \u003cb\u003eTo App\u003c/b\u003e from \u003cb\u003eReverse Proxy\u003c/b\u003e to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-authentication@reverse-proxy\u003eto-app@reverse-proxy@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"cross-site-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"very-likely","exploitation_impact":"low","title":"\u003cb\u003eCross-Site Request Forgery (CSRF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e via \u003cb\u003eDirect to App (no proxy)\u003c/b\u003e from \u003cb\u003eUser Browser\u003c/b\u003e","synthetic_id":"cross-site-request-forgery@juice-shop@user-browser\u003edirect-to-app-no-proxy","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"user-browser\u003edirect-to-app-no-proxy","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"cross-site-request-forgery","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"very-likely","exploitation_impact":"low","title":"\u003cb\u003eCross-Site Request Forgery (CSRF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e via \u003cb\u003eTo App\u003c/b\u003e from \u003cb\u003eReverse Proxy\u003c/b\u003e","synthetic_id":"cross-site-request-forgery@juice-shop@reverse-proxy\u003eto-app","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"reverse-proxy\u003eto-app","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"unencrypted-asset","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eUnencrypted Technical Asset\u003c/b\u003e named \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"unencrypted-asset@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"unnecessary-data-transfer","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Data Transfer\u003c/b\u003e of \u003cb\u003eTokens \u0026 Sessions\u003c/b\u003e data at \u003cb\u003eUser Browser\u003c/b\u003e from/to \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"unnecessary-data-transfer@tokens-sessions@user-browser@juice-shop","most_relevant_data_asset":"tokens-sessions","most_relevant_technical_asset":"user-browser","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["user-browser"]},{"category":"unnecessary-data-transfer","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Data Transfer\u003c/b\u003e of \u003cb\u003eTokens \u0026 Sessions\u003c/b\u003e data at \u003cb\u003eUser Browser\u003c/b\u003e from/to \u003cb\u003eReverse Proxy\u003c/b\u003e","synthetic_id":"unnecessary-data-transfer@tokens-sessions@user-browser@reverse-proxy","most_relevant_data_asset":"tokens-sessions","most_relevant_technical_asset":"user-browser","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["user-browser"]},{"category":"cross-site-scripting","risk_status":"unchecked","severity":"elevated","exploitation_likelihood":"likely","exploitation_impact":"medium","title":"\u003cb\u003eCross-Site Scripting (XSS)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"cross-site-scripting@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"container-baseimage-backdooring","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eContainer Base Image Backdooring\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"container-baseimage-backdooring@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"probable","data_breach_technical_assets":["juice-shop"]},{"category":"unencrypted-communication","risk_status":"unchecked","severity":"elevated","exploitation_likelihood":"likely","exploitation_impact":"high","title":"\u003cb\u003eUnencrypted Communication\u003c/b\u003e named \u003cb\u003eDirect to App (no proxy)\u003c/b\u003e between \u003cb\u003eUser Browser\u003c/b\u003e and \u003cb\u003eJuice Shop Application\u003c/b\u003e transferring authentication data (like credentials, token, session-id, etc.)","synthetic_id":"unencrypted-communication@user-browser\u003edirect-to-app-no-proxy@user-browser@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"user-browser","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"user-browser\u003edirect-to-app-no-proxy","data_breach_probability":"possible","data_breach_technical_assets":["juice-shop"]},{"category":"unnecessary-technical-asset","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Technical Asset\u003c/b\u003e named \u003cb\u003ePersistent Storage\u003c/b\u003e","synthetic_id":"unnecessary-technical-asset@persistent-storage","most_relevant_data_asset":"","most_relevant_technical_asset":"persistent-storage","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["persistent-storage"]},{"category":"unnecessary-technical-asset","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eUnnecessary Technical Asset\u003c/b\u003e named \u003cb\u003eUser Browser\u003c/b\u003e","synthetic_id":"unnecessary-technical-asset@user-browser","most_relevant_data_asset":"","most_relevant_technical_asset":"user-browser","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["user-browser"]},{"category":"missing-hardening","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eMissing Hardening\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-hardening@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]},{"category":"missing-hardening","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"likely","exploitation_impact":"low","title":"\u003cb\u003eMissing Hardening\u003c/b\u003e risk at \u003cb\u003ePersistent Storage\u003c/b\u003e","synthetic_id":"missing-hardening@persistent-storage","most_relevant_data_asset":"","most_relevant_technical_asset":"persistent-storage","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["persistent-storage"]},{"category":"missing-build-infrastructure","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Build Infrastructure\u003c/b\u003e in the threat model (referencing asset \u003cb\u003eJuice Shop Application\u003c/b\u003e as an example)","synthetic_id":"missing-build-infrastructure@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":[]},{"category":"missing-vault","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eMissing Vault (Secret Storage)\u003c/b\u003e in the threat model (referencing asset \u003cb\u003eJuice Shop Application\u003c/b\u003e as an example)","synthetic_id":"missing-vault@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":[]},{"category":"missing-waf","risk_status":"unchecked","severity":"low","exploitation_likelihood":"unlikely","exploitation_impact":"low","title":"\u003cb\u003eMissing Web Application Firewall (WAF)\u003c/b\u003e risk at \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"missing-waf@juice-shop","most_relevant_data_asset":"","most_relevant_technical_asset":"juice-shop","most_relevant_trust_boundary":"","most_relevant_shared_runtime":"","most_relevant_communication_link":"","data_breach_probability":"improbable","data_breach_technical_assets":["juice-shop"]}]
\ No newline at end of file
diff --git a/labs/lab2/secure/stats.json b/labs/lab2/secure/stats.json
new file mode 100644
index 00000000..b57e372b
--- /dev/null
+++ b/labs/lab2/secure/stats.json
@@ -0,0 +1 @@
+{"risks":{"critical":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"elevated":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":3},"high":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":0},"low":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":5},"medium":{"accepted":0,"false-positive":0,"in-discussion":0,"in-progress":0,"mitigated":0,"unchecked":13}}}
\ No newline at end of file
diff --git a/labs/lab2/secure/technical-assets.json b/labs/lab2/secure/technical-assets.json
new file mode 100644
index 00000000..ea528fe1
--- /dev/null
+++ b/labs/lab2/secure/technical-assets.json
@@ -0,0 +1 @@
+{"juice-shop":{"Id":"juice-shop","Title":"Juice Shop Application","Description":"OWASP Juice Shop server (Node.js/Express, v19.0.0).","Usage":0,"Type":1,"Size":2,"Technology":6,"Machine":2,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":true,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"In-scope web application (contains all business logic and vulnerabilities by design).","Tags":["app","nodejs"],"DataAssetsProcessed":["user-accounts","orders","product-catalog","tokens-sessions"],"DataAssetsStored":["logs"],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"juice-shop\u003eto-challenge-webhook","SourceId":"juice-shop","TargetId":"webhook-endpoint","Title":"To Challenge WebHook","Description":"Optional outbound callback (HTTP POST) to external WebHook when a challenge is solved.","Protocol":2,"Tags":["egress"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["orders"],"DataAssetsReceived":null,"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":70.02881844380403},"persistent-storage":{"Id":"persistent-storage","Title":"Persistent Storage","Description":"Host-mounted volume for database, file uploads, and logs.","Usage":1,"Type":2,"Size":3,"Technology":10,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":1,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Local disk storage for the container – not directly exposed, but if compromised it contains sensitive data (database and logs).","Tags":["storage","volume"],"DataAssetsProcessed":[],"DataAssetsStored":["logs","user-accounts","orders","product-catalog"],"DataFormatsAccepted":[3],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":100},"reverse-proxy":{"Id":"reverse-proxy","Title":"Reverse Proxy","Description":"Optional reverse proxy (e.g., Nginx) for TLS termination and adding security headers.","Usage":0,"Type":1,"Size":2,"Technology":20,"Machine":1,"Internet":false,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":false,"Encryption":1,"JustificationOutOfScope":"","Owner":"Lab Owner","Confidentiality":1,"Integrity":2,"Availability":2,"JustificationCiaRating":"Not exposed to internet directly; improves security of inbound traffic.","Tags":["optional","proxy"],"DataAssetsProcessed":["product-catalog","tokens-sessions"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"reverse-proxy\u003eto-app","SourceId":"reverse-proxy","TargetId":"juice-shop","Title":"To App","Description":"Proxy forwarding to app (HTTP on 3000 internally).","Protocol":2,"Tags":[],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":0,"Authorization":0,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":9.623538157950035},"user-browser":{"Id":"user-browser","Title":"User Browser","Description":"End-user web browser (client).","Usage":0,"Type":0,"Size":0,"Technology":2,"Machine":1,"Internet":true,"MultiTenant":false,"Redundant":false,"CustomDevelopedParts":false,"OutOfScope":false,"UsedAsClientByHuman":true,"Encryption":0,"JustificationOutOfScope":"","Owner":"External User","Confidentiality":0,"Integrity":1,"Availability":1,"JustificationCiaRating":"Client controlled by end user (potentially an attacker).","Tags":["actor","user"],"DataAssetsProcessed":[],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[{"Id":"user-browser\u003eto-reverse-proxy-preferred","SourceId":"user-browser","TargetId":"reverse-proxy","Title":"To Reverse Proxy (preferred)","Description":"User browser to reverse proxy (HTTPS on 443).","Protocol":2,"Tags":["primary"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true},{"Id":"user-browser\u003edirect-to-app-no-proxy","SourceId":"user-browser","TargetId":"juice-shop","Title":"Direct to App (no proxy)","Description":"Direct browser access to app (HTTP on 3000).","Protocol":1,"Tags":["direct"],"VPN":false,"IpFiltered":false,"Readonly":false,"Authentication":2,"Authorization":2,"Usage":0,"DataAssetsSent":["tokens-sessions"],"DataAssetsReceived":["product-catalog"],"DiagramTweakWeight":1,"DiagramTweakConstraint":true}],"DiagramTweakOrder":0,"RAA":25.859639506459924},"webhook-endpoint":{"Id":"webhook-endpoint","Title":"Webhook Endpoint","Description":"External WebHook service (3rd-party, if configured for integrations).","Usage":0,"Type":0,"Size":0,"Technology":14,"Machine":1,"Internet":true,"MultiTenant":true,"Redundant":true,"CustomDevelopedParts":false,"OutOfScope":true,"UsedAsClientByHuman":false,"Encryption":0,"JustificationOutOfScope":"Third-party service to receive notifications (not under our control).","Owner":"Third-Party","Confidentiality":1,"Integrity":1,"Availability":1,"JustificationCiaRating":"External service that receives data (like order or challenge info). Treated as a trusted integration point but could be abused if misconfigured.","Tags":["saas","webhook"],"DataAssetsProcessed":["orders"],"DataAssetsStored":[],"DataFormatsAccepted":[0],"CommunicationLinks":[],"DiagramTweakOrder":0,"RAA":1}}
\ No newline at end of file
diff --git a/labs/lab2/threagile-model.secure.yaml b/labs/lab2/threagile-model.secure.yaml
new file mode 100644
index 00000000..56c4ab42
--- /dev/null
+++ b/labs/lab2/threagile-model.secure.yaml
@@ -0,0 +1,429 @@
+threagile_version: 1.0.0
+
+title: OWASP Juice Shop — Local Lab Threat Model
+date: 2025-09-18
+
+author:
+ name: Student Name
+ homepage: https://example.edu
+
+management_summary_comment: >
+ Threat model for a local OWASP Juice Shop setup. Users access the app
+ either directly via HTTP on port 3000 or through an optional reverse proxy that
+ terminates TLS and adds security headers. The app runs in a container
+ and writes data to a host-mounted volume (for database, uploads, logs).
+ Optional outbound notifications (e.g., a challenge-solution WebHook) can be configured for integrations.
+
+business_criticality: important # archive, operational, important, critical, mission-critical
+
+business_overview:
+ description: >
+ Training environment for DevSecOps. This model covers a deliberately vulnerable
+ web application (OWASP Juice Shop) running locally in a Docker container. The focus is on a minimal architecture, STRIDE threat analysis, and actionable mitigations for the identified risks.
+
+ images:
+ # - dfd.png: Data Flow Diagram (if exported from the tool)
+
+technical_overview:
+ description: >
+ A user’s web browser connects to the Juice Shop application (Node.js/Express server) either directly on **localhost:3000** (HTTP) or via a **reverse proxy** on ports 80/443 (with HTTPS). The Juice Shop server may issue outbound requests to external services (e.g., a configured **WebHook** for solved challenge notifications). All application data (the SQLite database, file uploads, logs) is stored on the host’s filesystem via a mounted volume. Key trust boundaries include the **Internet** (user & external services) → **Host** (local machine/VM) → **Container Network** (isolated app container).
+ images: []
+
+questions:
+ Do you expose port 3000 beyond localhost?: ""
+ Do you use a reverse proxy with TLS and security headers?: ""
+ Are any outbound integrations (webhooks) configured?: ""
+ Is any sensitive data stored in logs or files?: ""
+
+abuse_cases:
+ Credential Stuffing / Brute Force: >
+ Attackers attempt repeated login attempts to guess credentials or exhaust system resources.
+ Stored XSS via Product Reviews: >
+ Malicious scripts are inserted into product reviews, getting stored and executed in other users’ browsers.
+ SSRF via Outbound Requests: >
+ Server-side requests (e.g. profile image URL fetch or WebHook callback) are abused to access internal network resources.
+
+security_requirements:
+ TLS in transit: Enforce HTTPS for user traffic via a TLS-terminating reverse proxy with strong ciphers and certificate management.
+ AuthZ on sensitive routes: Implement strict server-side authorization checks (role/permission) on admin or sensitive functionalities.
+ Rate limiting & lockouts: Apply rate limiting and account lockout policies to mitigate brute-force and automated attacks on authentication and expensive operations.
+ Secure headers: Add security headers (HSTS, CSP, X-Frame-Options, X-Content-Type-Options, etc.) at the proxy or app to mitigate client-side attacks.
+ Secrets management: Protect secret keys and credentials (JWT signing keys, OAuth client secrets) – keep them out of code repos and avoid logging them.
+
+tags_available:
+ # Relevant technologies and environment tags
+ - docker
+ - nodejs
+ # Data and asset tags
+ - pii
+ - auth
+ - tokens
+ - logs
+ - public
+ - actor
+ - user
+ - optional
+ - proxy
+ - app
+ - storage
+ - volume
+ - saas
+ - webhook
+ # Communication tags
+ - primary
+ - direct
+ - egress
+
+# =========================
+# DATA ASSETS
+# =========================
+data_assets:
+
+ User Accounts:
+ id: user-accounts
+ description: "User profile data, credential hashes, emails."
+ usage: business
+ tags: ["pii", "auth"]
+ origin: user-supplied
+ owner: Lab Owner
+ quantity: many
+ confidentiality: confidential
+ integrity: critical
+ availability: important
+ justification_cia_rating: >
+ Contains personal identifiers and authentication data. High confidentiality is required to protect user privacy, and integrity is critical to prevent account takeovers.
+
+ Orders:
+ id: orders
+ description: "Order history, addresses, and payment metadata (no raw card numbers)."
+ usage: business
+ tags: ["pii"]
+ origin: application
+ owner: Lab Owner
+ quantity: many
+ confidentiality: confidential
+ integrity: important
+ availability: important
+ justification_cia_rating: >
+ Contains users’ personal data and business transaction records. Integrity and confidentiality are important to prevent fraud or privacy breaches.
+
+ Product Catalog:
+ id: product-catalog
+ description: "Product information (names, descriptions, prices) available to all users."
+ usage: business
+ tags: ["public"]
+ origin: application
+ owner: Lab Owner
+ quantity: many
+ confidentiality: public
+ integrity: important
+ availability: important
+ justification_cia_rating: >
+ Product data is intended to be public, but its integrity is important (to avoid defacement or price manipulation that could mislead users).
+
+ Tokens & Sessions:
+ id: tokens-sessions
+ description: "Session identifiers, JWTs for authenticated sessions, CSRF tokens."
+ usage: business
+ tags: ["auth", "tokens"]
+ origin: application
+ owner: Lab Owner
+ quantity: many
+ confidentiality: confidential
+ integrity: important
+ availability: important
+ justification_cia_rating: >
+ If session tokens are compromised, attackers can hijack user sessions. They must be kept confidential and intact; availability is less critical (tokens can be reissued).
+
+ Logs:
+ id: logs
+ description: "Application and access logs (may inadvertently contain PII or secrets)."
+ usage: devops
+ tags: ["logs"]
+ origin: application
+ owner: Lab Owner
+ quantity: many
+ confidentiality: internal
+ integrity: important
+ availability: important
+ justification_cia_rating: >
+ Logs are for internal use (troubleshooting, monitoring). They should not be exposed publicly, and sensitive data should be sanitized to protect confidentiality.
+
+# =========================
+# TECHNICAL ASSETS
+# =========================
+technical_assets:
+
+ User Browser:
+ id: user-browser
+ description: "End-user web browser (client)."
+ type: external-entity
+ usage: business
+ used_as_client_by_human: true
+ out_of_scope: false
+ justification_out_of_scope:
+ size: system
+ technology: browser
+ tags: ["actor", "user"]
+ internet: true
+ machine: virtual
+ encryption: none
+ owner: External User
+ confidentiality: public
+ integrity: operational
+ availability: operational
+ justification_cia_rating: "Client controlled by end user (potentially an attacker)."
+ multi_tenant: false
+ redundant: false
+ custom_developed_parts: false
+ data_assets_processed: []
+ data_assets_stored: []
+ data_formats_accepted:
+ - json
+ communication_links:
+ To Reverse Proxy (preferred):
+ target: reverse-proxy
+ description: "User browser to reverse proxy (HTTPS on 443)."
+ protocol: https
+ authentication: session-id
+ authorization: enduser-identity-propagation
+ tags: ["primary"]
+ vpn: false
+ ip_filtered: false
+ readonly: false
+ usage: business
+ data_assets_sent:
+ - tokens-sessions
+ data_assets_received:
+ - product-catalog
+ Direct to App (no proxy):
+ target: juice-shop
+ description: "Direct browser access to app (HTTP on 3000)."
+ protocol: http
+ authentication: session-id
+ authorization: enduser-identity-propagation
+ tags: ["direct"]
+ vpn: false
+ ip_filtered: false
+ readonly: false
+ usage: business
+ data_assets_sent:
+ - tokens-sessions
+ data_assets_received:
+ - product-catalog
+
+ Reverse Proxy:
+ id: reverse-proxy
+ description: "Optional reverse proxy (e.g., Nginx) for TLS termination and adding security headers."
+ type: process
+ usage: business
+ used_as_client_by_human: false
+ out_of_scope: false
+ justification_out_of_scope:
+ size: application
+ technology: reverse-proxy
+ tags: ["optional", "proxy"]
+ internet: false
+ machine: virtual
+ encryption: transparent
+ owner: Lab Owner
+ confidentiality: internal
+ integrity: important
+ availability: important
+ justification_cia_rating: "Not exposed to internet directly; improves security of inbound traffic."
+ multi_tenant: false
+ redundant: false
+ custom_developed_parts: false
+ data_assets_processed:
+ - product-catalog
+ - tokens-sessions
+ data_assets_stored: []
+ data_formats_accepted:
+ - json
+ communication_links:
+ To App:
+ target: juice-shop
+ description: "Proxy forwarding to app (HTTP on 3000 internally)."
+ protocol: https
+ authentication: none
+ authorization: none
+ tags: []
+ vpn: false
+ ip_filtered: false
+ readonly: false
+ usage: business
+ data_assets_sent:
+ - tokens-sessions
+ data_assets_received:
+ - product-catalog
+
+ Juice Shop Application:
+ id: juice-shop
+ description: "OWASP Juice Shop server (Node.js/Express, v19.0.0)."
+ type: process
+ usage: business
+ used_as_client_by_human: false
+ out_of_scope: false
+ justification_out_of_scope:
+ size: application
+ technology: web-server
+ tags: ["app", "nodejs"]
+ internet: false
+ machine: container
+ encryption: none
+ owner: Lab Owner
+ confidentiality: internal
+ integrity: important
+ availability: important
+ justification_cia_rating: "In-scope web application (contains all business logic and vulnerabilities by design)."
+ multi_tenant: false
+ redundant: false
+ custom_developed_parts: true
+ data_assets_processed:
+ - user-accounts
+ - orders
+ - product-catalog
+ - tokens-sessions
+ data_assets_stored:
+ - logs
+ data_formats_accepted:
+ - json
+ communication_links:
+ To Challenge WebHook:
+ target: webhook-endpoint
+ description: "Optional outbound callback (HTTP POST) to external WebHook when a challenge is solved."
+ protocol: https
+ authentication: none
+ authorization: none
+ tags: ["egress"]
+ vpn: false
+ ip_filtered: false
+ readonly: false
+ usage: business
+ data_assets_sent:
+ - orders
+
+ Persistent Storage:
+ id: persistent-storage
+ description: "Host-mounted volume for database, file uploads, and logs."
+ type: datastore
+ usage: devops
+ used_as_client_by_human: false
+ out_of_scope: false
+ justification_out_of_scope:
+ size: component
+ technology: file-server
+ tags: ["storage", "volume"]
+ internet: false
+ machine: virtual
+ encryption: transparent
+ owner: Lab Owner
+ confidentiality: internal
+ integrity: important
+ availability: important
+ justification_cia_rating: "Local disk storage for the container – not directly exposed, but if compromised it contains sensitive data (database and logs)."
+ multi_tenant: false
+ redundant: false
+ custom_developed_parts: false
+ data_assets_processed: []
+ data_assets_stored:
+ - logs
+ - user-accounts
+ - orders
+ - product-catalog
+ data_formats_accepted:
+ - file
+ communication_links: {}
+
+ Webhook Endpoint:
+ id: webhook-endpoint
+ description: "External WebHook service (3rd-party, if configured for integrations)."
+ type: external-entity
+ usage: business
+ used_as_client_by_human: false
+ out_of_scope: true
+ justification_out_of_scope: "Third-party service to receive notifications (not under our control)."
+ size: system
+ technology: web-service-rest
+ tags: ["saas", "webhook"]
+ internet: true
+ machine: virtual
+ encryption: none
+ owner: Third-Party
+ confidentiality: internal
+ integrity: operational
+ availability: operational
+ justification_cia_rating: "External service that receives data (like order or challenge info). Treated as a trusted integration point but could be abused if misconfigured."
+ multi_tenant: true
+ redundant: true
+ custom_developed_parts: false
+ data_assets_processed:
+ - orders
+ data_assets_stored: []
+ data_formats_accepted:
+ - json
+ communication_links: {}
+
+# =========================
+# TRUST BOUNDARIES
+# =========================
+trust_boundaries:
+
+ Internet:
+ id: internet
+ description: "Untrusted public network (Internet)."
+ type: network-dedicated-hoster
+ tags: []
+ technical_assets_inside:
+ - user-browser
+ - webhook-endpoint
+ trust_boundaries_nested:
+ - host
+
+ Host:
+ id: host
+ description: "Local host machine / VM running the Docker environment."
+ type: network-dedicated-hoster
+ tags: []
+ technical_assets_inside:
+ - reverse-proxy
+ - persistent-storage
+ trust_boundaries_nested:
+ - container-network
+
+ Container Network:
+ id: container-network
+ description: "Docker container network (isolated internal network for containers)."
+ type: network-dedicated-hoster
+ tags: []
+ technical_assets_inside:
+ - juice-shop
+ trust_boundaries_nested: []
+
+# =========================
+# SHARED RUNTIMES
+# =========================
+shared_runtimes:
+
+ Docker Host:
+ id: docker-host
+ description: "Docker Engine and default bridge network on the host."
+ tags: ["docker"]
+ technical_assets_running:
+ - juice-shop
+ # If the reverse proxy is containerized, include it:
+ # - reverse-proxy
+
+# =========================
+# INDIVIDUAL RISK CATEGORIES (optional)
+# =========================
+individual_risk_categories: {}
+
+# =========================
+# RISK TRACKING (optional)
+# =========================
+risk_tracking: {}
+
+# (Optional diagram layout tweaks can be added here)
+#diagram_tweak_edge_layout: spline
+#diagram_tweak_layout_left_to_right: true
diff --git a/labs/lab3.md b/labs/lab3.md
index 47ec06df..fe05e44e 100644
--- a/labs/lab3.md
+++ b/labs/lab3.md
@@ -47,7 +47,7 @@ Study why commit signing is crucial for verifying the integrity and authenticity
```sh
git config --global user.signingkey
git config --global commit.gpgSign true
- git config --global gpg.format ssh
+
```
#### 1.3: Create Signed Commit
diff --git a/labs/lab7.md b/labs/lab7.md
deleted file mode 100644
index 48c23111..00000000
--- a/labs/lab7.md
+++ /dev/null
@@ -1,414 +0,0 @@
-# Lab 7 — Container Security: Image Scanning & Deployment Hardening
-
-
-
-
-
-> **Goal:** Analyze container images for vulnerabilities, audit Docker host security, and compare secure deployment configurations.
-> **Deliverable:** A PR from `feature/lab7` to the course repo with `labs/submission7.md` containing vulnerability analysis, CIS benchmark results, and deployment security comparison. Submit the PR link via Moodle.
-
----
-
-## Overview
-
-In this lab you will practice:
-- **Container image vulnerability scanning** using next-generation tools (Docker Scout, Snyk)
-- **Docker security benchmarking** with CIS Docker Benchmark compliance assessment
-- **Secure container deployment** analysis and configuration comparison
-- **Container security assessment** using modern scanning and analysis tools
-- **Security configuration impact** analysis for production deployments
-
-These skills are essential for implementing container security in DevSecOps pipelines and production environments.
-
-> Target application: OWASP Juice Shop (`bkimminich/juice-shop:v19.0.0`)
-
----
-
-## Prerequisites
-
-### Docker Scout CLI Setup
-
-Docker Scout requires authentication and a CLI plugin installation.
-
-#### Step 1: Install Docker Scout CLI Plugin
-
-**For Linux/macOS:**
-```bash
-curl -sSfL https://raw.githubusercontent.com/docker/scout-cli/main/install.sh | sh -s --
-```
-
-**Verify installation:**
-```bash
-docker scout version
-```
-
-You should see output like: `version: v1.x.x`
-
-#### Step 2: Docker Hub Authentication
-
-Docker Scout requires a Docker Hub account and Personal Access Token (PAT).
-
-**Create account and generate PAT:**
-
-1. **Create Docker Hub account** (if needed): Visit https://hub.docker.com
-
-2. **Generate PAT:**
-
- - Log in → Account Settings → Security → Personal Access Tokens
- - Click **New Access Token**
- - Description: `Lab7 Docker Scout Access`
- - Permissions: Select **Read, Write, Delete**
- - Click **Generate** and copy the token immediately
-
-3. **Authenticate:**
-
- ```bash
- docker login
- # Username: your-docker-hub-username
- # Password: paste-your-PAT (not your password!)
- ```
-
-4. **Verify access:**
-
- ```bash
- docker scout quickview busybox:latest
- # Should display vulnerability scan results
- ```
-
-**Why PAT over password?**
-- Limited scope permissions for least privilege
-- Easy to revoke without changing account password
-- Required for SSO-enabled organizations
-- Better audit trail
-
-Learn more: https://docs.docker.com/go/access-tokens/
-
----
-
-## Tasks
-
-### Task 1 — Image Vulnerability & Configuration Analysis (3 pts)
-
-**Objective:** Scan container images for vulnerabilities and configuration issues.
-
-#### 1.1: Setup Working Directory
-
-```bash
-mkdir -p labs/lab7/{scanning,hardening,analysis}
-cd labs/lab7
-```
-
-#### 1.2: Vulnerability Scanning
-
-```bash
-# Pull the image to scan locally
-docker pull bkimminich/juice-shop:v19.0.0
-
-# Detailed CVE analysis
-docker scout cves bkimminich/juice-shop:v19.0.0 | tee scanning/scout-cves.txt
-```
-
-**Understanding the output:**
-- **C/H/M/L** = Critical/High/Medium/Low severity counts
-- Look for CVE IDs, affected packages, and potential impact
-
-#### 1.3: Snyk comparison
-
-```bash
-# Requires Snyk account: https://snyk.io
-# Set token: export SNYK_TOKEN=your-token
-docker run --rm \
- -e SNYK_TOKEN \
- -v /var/run/docker.sock:/var/run/docker.sock \
- snyk/snyk:docker snyk test --docker bkimminich/juice-shop:v19.0.0 --severity-threshold=high \
- | tee scanning/snyk-results.txt
-```
-
-#### 1.4: Configuration Assessment
-
-```bash
-# Scan for security and best practice issues
-docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
- goodwithtech/dockle:latest \
- bkimminich/juice-shop:v19.0.0 | tee scanning/dockle-results.txt
-```
-
-**Look for:**
-- **FATAL/WARN** issues about running as root
-- Exposed secrets in environment variables
-- Missing security configurations
-- File permission issues
-
-**📊 Document in `labs/submission7.md`:**
-
-1. **Top 5 Critical/High Vulnerabilities**
- - CVE ID, affected package, severity, and impact
-
-2. **Dockle Configuration Findings**
- - List FATAL and WARN issues
- - Explain why each is a security concern
-
-3. **Security Posture Assessment**
- - Does the image run as root?
- - What security improvements would you recommend?
-
----
-
-### Task 2 — Docker Host Security Benchmarking (3 pts)
-
-**Objective:** Audit Docker host configuration against CIS Docker Benchmark.
-
-#### 2.1: Run CIS Docker Benchmark
-
-```bash
-# Run CIS Docker Benchmark security audit
-docker run --rm --net host --pid host --userns host --cap-add audit_control \
- -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
- -v /var/lib:/var/lib:ro \
- -v /var/run/docker.sock:/var/run/docker.sock:ro \
- -v /usr/lib/systemd:/usr/lib/systemd:ro \
- -v /etc:/etc:ro --label docker_bench_security \
- docker/docker-bench-security | tee hardening/docker-bench-results.txt
-```
-
-**Understanding the output:**
-- **[PASS]** - Security control properly configured
-- **[WARN]** - Potential issue requiring review
-- **[FAIL]** - Security control not properly configured
-- **[INFO]** - Informational (no action needed)
-
-**Key sections:**
-1. Host Configuration
-2. Docker daemon configuration
-3. Docker daemon configuration files
-4. Container Images and Build Files
-5. Container Runtime
-
-**📊 Document in `labs/submission7.md`:**
-
-1. **Summary Statistics**
- - Total PASS/WARN/FAIL/INFO counts
-
-2. **Analysis of Failures** (if any)
- - List failures and explain security impact
- - Propose specific remediation steps
-
----
-
-### Task 3 — Deployment Security Configuration Analysis (4 pts)
-
-**Objective:** Compare deployment configurations to understand security hardening trade-offs.
-
-#### 3.1: Deploy Three Security Profiles
-
-```bash
-# Profile 1: Default (baseline)
-docker run -d --name juice-default -p 3001:3000 \
- bkimminich/juice-shop:v19.0.0
-
-# Profile 2: Hardened (security restrictions)
-docker run -d --name juice-hardened -p 3002:3000 \
- --cap-drop=ALL \
- --security-opt=no-new-privileges \
- --memory=512m \
- --cpus=1.0 \
- bkimminich/juice-shop:v19.0.0
-
-# Profile 3: Production (maximum hardening)
-docker run -d --name juice-production -p 3003:3000 \
- --cap-drop=ALL \
- --cap-add=NET_BIND_SERVICE \
- --security-opt=no-new-privileges \
- --security-opt=seccomp=default \
- --memory=512m \
- --memory-swap=512m \
- --cpus=1.0 \
- --pids-limit=100 \
- --restart=on-failure:3 \
- bkimminich/juice-shop:v19.0.0
-
-# Wait for startup
-sleep 15
-
-# Verify all containers are running
-docker ps -a --filter name=juice-
-```
-
-#### 3.2: Compare Configurations
-
-```bash
-# Test functionality
-echo "=== Functionality Test ===" | tee analysis/deployment-comparison.txt
-curl -s -o /dev/null -w "Default: HTTP %{http_code}\n" http://localhost:3001 | tee -a analysis/deployment-comparison.txt
-curl -s -o /dev/null -w "Hardened: HTTP %{http_code}\n" http://localhost:3002 | tee -a analysis/deployment-comparison.txt
-curl -s -o /dev/null -w "Production: HTTP %{http_code}\n" http://localhost:3003 | tee -a analysis/deployment-comparison.txt
-
-# Check resource usage
-echo "" | tee -a analysis/deployment-comparison.txt
-echo "=== Resource Usage ===" | tee -a analysis/deployment-comparison.txt
-docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" \
- juice-default juice-hardened juice-production | tee -a analysis/deployment-comparison.txt
-
-# Inspect security settings
-echo "" | tee -a analysis/deployment-comparison.txt
-echo "=== Security Configurations ===" | tee -a analysis/deployment-comparison.txt
-for container in juice-default juice-hardened juice-production; do
- echo "" | tee -a analysis/deployment-comparison.txt
- echo "Container: $container" | tee -a analysis/deployment-comparison.txt
- docker inspect $container --format 'CapDrop: {{.HostConfig.CapDrop}}
-SecurityOpt: {{.HostConfig.SecurityOpt}}
-Memory: {{.HostConfig.Memory}}
-CPU: {{.HostConfig.CpuQuota}}
-PIDs: {{.HostConfig.PidsLimit}}
-Restart: {{.HostConfig.RestartPolicy.Name}}' | tee -a analysis/deployment-comparison.txt
-done
-```
-
-#### 3.3: Cleanup
-
-```bash
-docker stop juice-default juice-hardened juice-production
-docker rm juice-default juice-hardened juice-production
-```
-
-**📊 Document in `labs/submission7.md`:**
-
-#### 1. Configuration Comparison Table
-
-Create a table from `docker inspect` output comparing all three profiles:
-- Capabilities (dropped/added)
-- Security options
-- Resource limits (memory, CPU, PIDs)
-- Restart policy
-
-#### 2. Security Measure Analysis
-
-Research and explain EACH security flag:
-
-**a) `--cap-drop=ALL` and `--cap-add=NET_BIND_SERVICE`**
-- What are Linux capabilities? (Research this!)
-- What attack vector does dropping ALL capabilities prevent?
-- Why do we need to add back NET_BIND_SERVICE?
-- What's the security trade-off?
-
-**b) `--security-opt=no-new-privileges`**
-- What does this flag do? (Look it up!)
-- What type of attack does it prevent?
-- Are there any downsides to enabling it?
-
-**c) `--memory=512m` and `--cpus=1.0`**
-- What happens if a container doesn't have resource limits?
-- What attack does memory limiting prevent?
-- What's the risk of setting limits too low?
-
-**d) `--pids-limit=100`**
-- What is a fork bomb?
-- How does PID limiting help?
-- How to determine the right limit?
-
-**e) `--restart=on-failure:3`**
-- What does this policy do?
-- When is auto-restart beneficial? When is it risky?
-- Compare `on-failure` vs `always`
-
-#### 3. Critical Thinking Questions
-
-1. **Which profile for DEVELOPMENT? Why?**
-
-2. **Which profile for PRODUCTION? Why?**
-
-3. **What real-world problem do resource limits solve?**
-
-4. **If an attacker exploits Default vs Production, what actions are blocked in Production?**
-
-5. **What additional hardening would you add?**
-
-
----
-
-## Acceptance Criteria
-
-- ✅ Branch `feature/lab7` exists with commits for each task
-- ✅ File `labs/submission7.md` contains required analysis for Tasks 1-3
-- ✅ Vulnerability scanning completed with Docker Scout
-- ✅ CIS Docker Benchmark audit completed
-- ✅ Deployment security comparison completed
-- ✅ All scan outputs committed to `labs/lab7/`
-- ✅ PR from `feature/lab7` → **course repo main branch** is open
-- ✅ PR link submitted via Moodle before the deadline
-
----
-
-## How to Submit
-
-1. Create a branch for this lab and push it to your fork:
-
- ```bash
- git switch -c feature/lab7
- # create labs/submission7.md with your findings
- git add labs/submission7.md labs/lab7/
- git commit -m "docs: add lab7 submission - container security analysis"
- git push -u origin feature/lab7
- ```
-
-2. Open a PR from your fork's `feature/lab7` branch → **course repository's main branch**.
-
-3. In the PR description, include:
-
- ```text
- - [x] Task 1 done — Advanced Image Security & Configuration Analysis
- - [x] Task 2 done — Docker Security Benchmarking & Assessment
- - [x] Task 3 done — Secure Container Deployment Analysis
- ```
-
-4. **Copy the PR URL** and submit it via **Moodle before the deadline**.
-
----
-
-## Rubric (10 pts)
-
-| Criterion | Points |
-| ---------------------------------------------------------------- | -----: |
-| Task 1 — Image vulnerability & configuration analysis | **3** |
-| Task 2 — Docker host security benchmarking | **3** |
-| Task 3 — Deployment security configuration analysis | **4** |
-| **Total** | **10** |
-
----
-
-## Guidelines
-
-- Use clear Markdown headers to organize sections in `submission7.md`
-- Include evidence from tool outputs to support your analysis
-- Research security concepts thoroughly—don't copy-paste
-- Focus on understanding trade-offs between security and usability
-
-
-Container Security Resources
-
-**Documentation:**
-- [Docker Security](https://docs.docker.com/engine/security/)
-- [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker)
-- [Linux Capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html)
-
-
-
-
-Expected Security Findings
-
-**Image Vulnerabilities:**
-- Outdated base packages with CVEs
-- Vulnerable dependencies
-- Missing security patches
-
-**CIS Benchmark:**
-- Insecure daemon configuration
-- Missing resource limits
-- Excessive privileges
-
-**Deployment Gaps:**
-- Running as root
-- Unnecessary capabilities
-- No resource limits
-
-
\ No newline at end of file
diff --git a/labs/screenshots/submission1/curl.png b/labs/screenshots/submission1/curl.png
new file mode 100644
index 00000000..2faa4480
Binary files /dev/null and b/labs/screenshots/submission1/curl.png differ
diff --git a/labs/screenshots/submission1/home-page.png b/labs/screenshots/submission1/home-page.png
new file mode 100644
index 00000000..cb99c995
Binary files /dev/null and b/labs/screenshots/submission1/home-page.png differ
diff --git a/labs/screenshots/submission1/sql-injection.png b/labs/screenshots/submission1/sql-injection.png
new file mode 100644
index 00000000..4677165f
Binary files /dev/null and b/labs/screenshots/submission1/sql-injection.png differ
diff --git a/labs/screenshots/submission3/blocked-commit.png b/labs/screenshots/submission3/blocked-commit.png
new file mode 100644
index 00000000..03c7809c
Binary files /dev/null and b/labs/screenshots/submission3/blocked-commit.png differ
diff --git a/labs/screenshots/submission3/signing-key.png b/labs/screenshots/submission3/signing-key.png
new file mode 100644
index 00000000..288474cb
Binary files /dev/null and b/labs/screenshots/submission3/signing-key.png differ
diff --git a/labs/screenshots/submission3/success-commit.png b/labs/screenshots/submission3/success-commit.png
new file mode 100644
index 00000000..1b55f6b5
Binary files /dev/null and b/labs/screenshots/submission3/success-commit.png differ
diff --git a/labs/screenshots/submission3/verified-commit.png b/labs/screenshots/submission3/verified-commit.png
new file mode 100644
index 00000000..c5f8b126
Binary files /dev/null and b/labs/screenshots/submission3/verified-commit.png differ
diff --git a/labs/submission1.md b/labs/submission1.md
new file mode 100644
index 00000000..366bf196
--- /dev/null
+++ b/labs/submission1.md
@@ -0,0 +1,52 @@
+# Triage Report — OWASP Juice Shop
+
+## Scope & Asset
+- Asset: OWASP Juice Shop (local lab instance)
+- Image: bkimminich/juice-shop:v19.0.0
+- Release link/date: [link](https://hub.docker.com/layers/bkimminich/juice-shop/v19.0.0/images/sha256-547bd3fef4a6d7e25e131da68f454e6dc4a59d281f8793df6853e6796c9bbf58) — 4 sept 2025
+- Image digest (optional): `sha256:547bd3fef4a6d7e25e131da68f454e6dc4a59d281f8793df6853e6796c9bbf58`
+
+## Environment
+- Host OS: `macOS 26.2`
+- Docker: 29.1.3
+
+## Deployment Details
+- Run command used: `docker run -d --name juice-shop -p 127.0.0.1:3000:3000 bkimminich/juice-shop:v19.0.0`
+- Access URL: http://127.0.0.1:3000
+- Network exposure: 127.0.0.1 only [V] Yes [ ] No (explain if No)
+
+## Health Check
+- Page load:
+
+
+
+- API check: first 5–10 lines from `curl -s http://127.0.0.1:3000/rest/products | head`
+
+```
+
+
+
+ Error: Unexpected path: /rest/products
+