diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 00000000..bfbeb41c
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,18 @@
+## Goal
+
+
+## Changes
+
+
+## Testing
+
+
+## Artifacts & Screenshots
+
+
+---
+
+### Checklist
+- [ ] PR title is clear and descriptive
+- [ ] Documentation updated if needed
+- [ ] No secrets or large temporary files committed
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..4c54d761
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..d22256ab
--- /dev/null
+++ b/labs/lab2/baseline/risks.json
@@ -0,0 +1 @@
+[{"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-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"]},{"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":"unencrypted-communication","risk_status":"unchecked","severity":"elevated","exploitation_likelihood":"likely","exploitation_impact":"medium","title":"\u003cb\u003eUnencrypted Communication\u003c/b\u003e named \u003cb\u003eTo App\u003c/b\u003e between \u003cb\u003eReverse Proxy\u003c/b\u003e and \u003cb\u003eJuice Shop Application\u003c/b\u003e","synthetic_id":"unencrypted-communication@reverse-proxy\u003eto-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\u003eto-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":"\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":"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":"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":"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":"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":"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":"unencrypted-asset","risk_status":"unchecked","severity":"medium","exploitation_likelihood":"unlikely","exploitation_impact":"medium","title":"\u003cb\u003eUnencrypted Technical Asset\u003c/b\u003e named \u003cb\u003ePersistent Storage\u003c/b\u003e","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":"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":"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":"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":"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":"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":"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"]}]
\ 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/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..5ead09e2
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..8a7567be
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..ce1714b5
--- /dev/null
+++ b/labs/lab2/secure/risks.json
@@ -0,0 +1 @@
+[{"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":"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":"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":"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":"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":"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-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-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":"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":"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":"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":"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":"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-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..c19a18a6
--- /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":2},"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..d2e318ef
--- /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 (HTTPS on 3000 internally in secure variant).","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 (HTTPS on 3000 in secure variant).","Protocol":2,"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..bd059834
--- /dev/null
+++ b/labs/lab2/threagile-model.secure.yaml
@@ -0,0 +1,440 @@
+threagile_version: 1.0.0
+
+title: OWASP Juice Shop — Local Lab Threat Model (Secure Variant)
+date: 2025-09-18
+
+author:
+ name: Student Name
+ homepage: https://example.edu
+
+management_summary_comment: >
+ Secure variant of the threat model for a local OWASP Juice Shop setup.
+ User traffic is forced over HTTPS (both direct and via reverse proxy),
+ and persistent storage is transparently encrypted. This variant demonstrates
+ how improving transport security and data-at-rest protections affects the
+ risk landscape compared to the baseline.
+
+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 secure variant focuses on improvements in transport encryption (HTTPS)
+ and encryption at rest, while keeping the overall architecture identical
+ to the baseline for meaningful comparison.
+
+ 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)
+ via HTTPS — either directly on **localhost:3000** (secured with TLS in this variant)
+ or via a **reverse proxy** on ports 80/443 (with HTTPS both externally and internally).
+ 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, which is now
+ modeled as **transparently encrypted**. 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?: "Yes, TLS is enforced"
+ 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 (HTTPS on 3000 in secure variant)."
+ protocol: https
+ 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 (HTTPS on 3000 internally in secure variant)."
+ 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/screenshot-juice-shop.png b/labs/screenshot-juice-shop.png
new file mode 100644
index 00000000..c02cf9cb
Binary files /dev/null and b/labs/screenshot-juice-shop.png differ
diff --git a/labs/submission1.md b/labs/submission1.md
new file mode 100644
index 00000000..47e54531
--- /dev/null
+++ b/labs/submission1.md
@@ -0,0 +1,94 @@
+# Lab 1 Submission — OWASP Juice Shop & PR Workflow
+
+## Task 1 — Triage Report: OWASP Juice Shop
+
+### Scope & Asset
+- **Asset:** OWASP Juice Shop (local lab instance)
+- **Image:** `bkimminich/juice-shop:v19.0.0`
+- **Release link/date:** [v19.0.0](https://github.com/juice-shop/juice-shop/releases/tag/v19.0.0) — 2025-09-04
+- **Image digest (optional):** `sha256:2765a26de7647609099a338d5b7f61085d95903c8703bb70f03fcc4b12f0818d`
+
+### Environment
+- **Host OS:** macOS 26.2 (Darwin 25.2.0)
+- **Docker:** 28.3.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 — [x] Yes — binding to `127.0.0.1:3000` does not expose the app to the local network.
+
+### Health Check
+- **Page load:** screenshot of the home page (http://localhost:3000):
+
+ 
+- **API check:** in v19 the products endpoint is `/api/Products`. Output (first lines):
+ ```bash
+ $ curl -s http://127.0.0.1:3000/api/Products | head -5
+ ```
+ ```
+ {"status":"success","data":[{"id":1,"name":"Apple Juice (1000ml)","description":"The all-time classic.","price":1.99,"deluxePrice":0.99,"image":"apple_juice.jpg","createdAt":"2026-02-10T20:20:01.147Z","updatedAt":"2026-02-10T20:20:01.147Z","deletedAt":null},{"id":2,"name":"Orange Juice (1000ml)","description":"Made from oranges hand-picked by Uncle Dittmeyer.","price":2.99,...
+ ```
+ API returns JSON with an array of products — deployment is working.
+
+### Surface Snapshot (Triage)
+- **Login/Registration visible:** [x] Yes — home page has login and registration buttons.
+- **Product listing/search present:** [x] Yes — product catalog and search are available.
+- **Admin or account area discoverable:** [x] Yes — account area is available after login; admin features are present in the app (intentionally vulnerable).
+- **Client-side errors in console:** [ ] Yes [x] No — *(check DevTools Console after page load and update if needed.)*
+- **Security headers (quick look):** output of `curl -I http://127.0.0.1:3000`:
+ ```
+ HTTP/1.1 200 OK
+ Access-Control-Allow-Origin: *
+ X-Content-Type-Options: nosniff
+ X-Frame-Options: SAMEORIGIN
+ Feature-Policy: payment 'self'
+ X-Recruiting: /#/jobs
+ Content-Type: text/html; charset=UTF-8
+ ...
+ ```
+ **CSP (Content-Security-Policy):** absent. **HSTS (Strict-Transport-Security):** absent. Present: X-Content-Type-Options, X-Frame-Options, Feature-Policy; header `Access-Control-Allow-Origin: *` allows cross-origin requests.
+
+### Risks Observed (Top 3)
+1. **Intentionally vulnerable application (training target)** — many known vulnerabilities (XSS, SQLi, broken auth, sensitive data exposure) for learning; such a stack is unacceptable in production.
+2. **Missing strict security headers** — typically no strict Content-Security-Policy or HSTS, increasing risk of XSS and downgrade attacks when deployed without a reverse proxy.
+3. **Open REST API without mandatory authentication** — endpoints such as `/api/Products` are accessible without authorization; in a real app, some data should be restricted by role.
+
+---
+
+## Task 2 — PR Template Setup
+
+### 2.1 Creation Process
+- File `.github/pull_request_template.md` was added to the repository.
+- The template includes sections: **Goal**, **Changes**, **Testing**, **Artifacts & Screenshots**.
+- A three-item checklist was added: clear PR title, documentation updated if needed, no secrets or large temporary files.
+
+### 2.2 Verification
+- The template must be committed and pushed to the **main** branch first, then create branch `feature/lab1` and open a PR to the course repo.
+- When creating a PR, the description will then be auto-filled from `.github/pull_request_template.md`.
+- **Evidence:** opening a new Pull Request on GitHub will show the description with all listed sections and the checklist.
+
+### How Templates Improve Collaboration
+- A consistent PR description format speeds up review: reviewers immediately see goal, changes, how it was tested, and artifacts.
+- The checklist reduces the risk of forgetting to update docs or accidentally committing secrets.
+- Templates set an expected quality bar and make the lab submission process predictable.
+
+---
+
+## Challenges & Solutions
+
+- **In v19 the products API at `/rest/products` returns an error.** Solution: in this version the path is `/api/Products`; the report uses the correct endpoint and verification output.
+- **Home page screenshot:** done manually — open http://localhost:3000, take a screenshot (Cmd+Shift+4 on macOS), save as `labs/screenshot-juice-shop.png` and add the image reference in the Health Check section.
+
+---
+
+## Task 6 — GitHub Community
+
+### GitHub Community
+
+**Why starring repositories matters:**
+Stars in open source act as both a bookmark for yourself and a signal to the community that the project is noticed and useful. They help maintainers see interest in the project and help other developers gauge popularity and topics. On your profile, stars reflect your interests and familiarity with modern tools.
+
+**How following developers helps in teamwork and growth:**
+Following instructors, TAs, and classmates lets you see their activity, commits, and projects in your feed. That makes it easier to find common ground, learn from others’ code, and stay in touch with people you may collaborate with later. For career growth, it helps to follow people working in stacks or domains you care about.
+
diff --git a/labs/submission2.md b/labs/submission2.md
new file mode 100644
index 00000000..35b08e5e
--- /dev/null
+++ b/labs/submission2.md
@@ -0,0 +1,184 @@
+# Lab 2 Submission — Threat Modeling with Threagile (OWASP Juice Shop)
+
+## Task 1 — Threagile Baseline Model
+
+### 1.1 Baseline Generation & Artifacts
+
+- **Model used:** `labs/lab2/threagile-model.yaml`
+- **Command:**
+
+```bash
+mkdir -p labs/lab2/baseline labs/lab2/secure
+
+docker run --rm -v "$(pwd)":/app/work threagile/threagile \
+ -model /app/work/labs/lab2/threagile-model.yaml \
+ -output /app/work/labs/lab2/baseline \
+ -generate-risks-excel=false -generate-tags-excel=false
+```
+
+- **Generated artifacts in `labs/lab2/baseline/`:**
+ - `report.pdf` — full report including diagrams
+ - PNG diagrams: data-flow, data-asset
+ - JSON exports: `risks.json`, `stats.json`, `technical-assets.json`
+
+### 1.2 Risk Ranking Methodology
+
+I used the formula provided in the lab:
+
+- **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
+- **Composite score:**
+ \[
+ \text{Score} = \text{Severity} \times 100 + \text{Likelihood} \times 10 + \text{Impact}
+ \]
+
+To calculate the top 5 risks I used `jq`:
+
+```bash
+jq -r '[.[] | {title, category, technical_asset, severity, likelihood, impact}
+ | . + {
+ sev:(.severity | if .=="critical" then 5 elif .=="elevated" then 4 elif .=="high" then 3 elif .=="medium" then 2 else 1 end),
+ lik:(.likelihood | if .=="very-likely" then 4 elif .=="likely" then 3 elif .=="possible" then 2 else 1 end),
+ imp:(.impact | if .=="high" then 3 elif .=="medium" then 2 else 1 end)
+ }
+ | . + {score:(.sev*100 + .lik*10 + .imp)}]
+ | sort_by(-.score) | .[0:5]
+ | ("title|category|asset|severity|likelihood|impact|score"),
+ ("-----|--------|-----|--------|----------|------|-----"),
+ (.[] | "\(.title)|\(.category)|\(.technical_asset)|\(.severity)|\(.likelihood)|\(.impact)|\(.score)")' \
+ labs/lab2/baseline/risks.json
+```
+
+### 1.3 Top 5 Risks (Baseline)
+
+| title | category | asset | severity | likelihood | impact | score |
+| ----- | -------- | ----- | -------- | ---------- | ------ | ----- |
+| `Unencrypted Communication named Direct to App (no proxy) between User Browser and Juice Shop Application transferring authentication data (like credentials, token, session-id, etc.)` | unencrypted-communication | null | elevated | null | null | 411 |
+| `Unencrypted Communication named To App between Reverse Proxy and Juice Shop Application` | unencrypted-communication | null | elevated | null | null | 411 |
+| `Cross-Site Scripting (XSS) risk at Juice Shop Application` | cross-site-scripting | null | elevated | null | null | 411 |
+| `Missing Authentication covering communication link To App from Reverse Proxy to Juice Shop Application` | missing-authentication | null | elevated | null | null | 411 |
+| `Missing Build Infrastructure in the threat model (referencing asset Juice Shop Application as an example)` | missing-build-infrastructure | null | medium | null | null | 211 |
+
+> **Note:** In the current Threagile output, the detailed `likelihood` and `impact` fields for these risks are not populated, so the resulting score is effectively driven by the mapped severity value. In manual analysis I treat them as at least `possible` and `medium` impact based on the application context (see below).
+
+### 1.4 Analysis of Key Risks
+
+- **Unencrypted Communication (Direct to App, Reverse Proxy → App):**
+ Lack of encryption for authentication data in transit exposes credentials and tokens to interception on the network (MITM, local network, malware). For a training environment this is acceptable, but in production all channels carrying tokens/sessions must be protected with HTTPS and HSTS.
+
+- **Cross-Site Scripting (XSS) in Juice Shop:**
+ Juice Shop is intentionally vulnerable to XSS; this enables session theft, actions on behalf of victims, and UI tampering. In a real e‑commerce system this would be one of the most critical risks.
+
+- **Missing Authentication (internal Reverse Proxy → App link):**
+ The absence of authentication on this internal hop makes lateral movement easier: if an attacker compromises the proxy or network, they can talk to the app directly. Typical compensating controls are mTLS or service‑level API keys between components.
+
+- **Missing Build Infrastructure:**
+ Not modeling CI/CD infrastructure hides an entire class of supply‑chain risks (pipeline compromise, malicious images). For a DevSecOps lab this is an important reminder that we must protect not only runtime but also build and delivery.
+
+### 1.5 Diagrams
+
+- **Data Flow Diagram:** auto‑generated in `labs/lab2/baseline/` and showing the main flows: browser → (optional) reverse proxy → Juice Shop → persistent storage / WebHook.
+- **Data Asset Diagram:** highlights that sensitive data (accounts, orders, tokens) converges in `Juice Shop Application` and `Persistent Storage`, making them primary attack targets.
+
+---
+
+## Task 2 — HTTPS Variant & Risk Comparison
+
+### 2.1 Secure Model Variant
+
+- **Model:** `labs/lab2/threagile-model.secure.yaml`
+- **Key changes compared to the baseline:**
+ - `User Browser → communication_links → Direct to App (no proxy)`: `protocol: https`
+ - `Reverse Proxy → communication_links → To App`: `protocol: https`
+ - `Persistent Storage`: `encryption: transparent`
+
+### 2.2 Secure Variant Report Generation
+
+```bash
+docker run --rm -v "$(pwd)":/app/work threagile/threagile \
+ -model /app/work/labs/lab2/threagile-model.secure.yaml \
+ -output /app/work/labs/lab2/secure \
+ -generate-risks-excel=false -generate-tags-excel=false
+```
+
+The `labs/lab2/secure/` directory contains the same artifact types: `report.pdf`, PNG diagrams, and JSON risk exports.
+
+### 2.3 Risk Category Delta Table
+
+To compare risk categories I used the command from the lab:
+
+```bash
+jq -n \
+ --slurpfile b labs/lab2/baseline/risks.json \
+ --slurpfile s labs/lab2/secure/risks.json '
+def tally(x):
+ (x | group_by(.category) | map({ (.[0].category): length }) | add) // {};
+ (tally($b[0])) as $B |
+ (tally($s[0])) as $S |
+ (($B + $S) | keys | sort) as $cats |
+ [
+ "| Category | Baseline | Secure | Δ |",
+ "|---|---:|---:|---:|"
+ ] + (
+ $cats | map(
+ "| " + . + " | " +
+ (($B[.] // 0) | tostring) + " | " +
+ (($S[.] // 0) | tostring) + " | " +
+ (((($S[.] // 0) - ($B[.] // 0))) | tostring) + " |"
+ )
+ ) | .[]'
+```
+
+**Resulting category table:**
+
+| Category | Baseline | Secure | Δ |
+|---|---:|---:|---:|
+| container-baseimage-backdooring | 1 | 1 | 0 |
+| cross-site-request-forgery | 2 | 2 | 0 |
+| cross-site-scripting | 1 | 1 | 0 |
+| missing-authentication | 1 | 1 | 0 |
+| missing-authentication-second-factor | 2 | 2 | 0 |
+| missing-build-infrastructure | 1 | 1 | 0 |
+| missing-hardening | 2 | 2 | 0 |
+| missing-identity-store | 1 | 1 | 0 |
+| missing-vault | 1 | 1 | 0 |
+| missing-waf | 1 | 1 | 0 |
+| server-side-request-forgery | 2 | 2 | 0 |
+| unencrypted-asset | 2 | 1 | -1 |
+| unencrypted-communication | 2 | 0 | -2 |
+| unnecessary-data-transfer | 2 | 2 | 0 |
+| unnecessary-technical-asset | 2 | 2 | 0 |
+
+### 2.4 Delta Run Explanation
+
+- **What changed in the model:**
+ - All user‑facing channels were switched to **HTTPS** (both direct access to the app and traffic via the reverse proxy).
+ - Internal traffic `Reverse Proxy → Juice Shop Application` was also switched to **HTTPS**, eliminating an unencrypted segment inside the host/container network.
+ - `Persistent Storage` is now modeled with **`encryption: transparent`**, representing disk/volume encryption.
+
+- **How this affected risks:**
+ - Category **`unencrypted-communication`** dropped from 2 risks to 0 (`Δ = -2`):
+ these two risks were in the baseline top‑5 (unencrypted Direct to App and Reverse Proxy → App links). After switching the protocol to HTTPS Threagile no longer reports them.
+ - Category **`unencrypted-asset`** decreased by one risk (`Δ = -1`), because encrypted persistent storage mitigates some threats tied to disk/volume compromise.
+ - Other categories (XSS, CSRF, missing‑*, etc.) remain unchanged, because enabling TLS and disk encryption does not fix application logic flaws or process/organizational gaps.
+
+- **Security interpretation:**
+ - **HTTPS + disk encryption** significantly improve protection **in transit** and **at rest**, but do not replace secure coding, testing, and hardening of the application itself.
+ - OWASP Top 10‑style issues (XSS, CSRF, broken auth) are still present and must be addressed by other measures (input validation, contextual output encoding, strict session management, security headers).
+ - Threagile clearly illustrates that “just adding TLS” is important but not sufficient: once cryptographic risks are reduced, logical and process risks remain prominent.
+
+### 2.5 Diagram Comparison
+
+- On the **data‑flow diagram** all user traffic arrows are now labeled HTTPS, including the internal path through the reverse proxy; this reflects the removal of passive sniffing opportunities.
+- On the **data‑asset diagram** the storage status changed: the persistent volume is marked as encrypted, which reduces blast radius if the host or disk is compromised.
+
+---
+
+## Summary
+
+- A baseline threat model for the local OWASP Juice Shop deployment was created and Threagile artifacts were generated automatically.
+- A formal prioritization (composite score) was performed and key risks around unencrypted traffic, XSS, and missing auth/hardening were identified.
+- A secure model variant with HTTPS everywhere and encrypted persistent storage was created, demonstrating reduced `unencrypted-communication` and `unencrypted-asset` categories.
+- All commands and results are documented in `labs/submission2.md` for reproducibility.
+