From 02239036f7eab831ca672eac515139f7ac6bc8c6 Mon Sep 17 00:00:00 2001 From: ratteperk Date: Fri, 12 Jun 2026 23:16:42 +0300 Subject: [PATCH] feat(lab2): Threagile threat model + secure variant + auth flow --- labs/lab2/threagile-model-auth.yaml | 370 ++++++++++++++++++++++ labs/lab2/threagile-model-secure.yaml | 429 ++++++++++++++++++++++++++ submissions/lab2.md | 94 ++++++ 3 files changed, 893 insertions(+) create mode 100644 labs/lab2/threagile-model-auth.yaml create mode 100755 labs/lab2/threagile-model-secure.yaml create mode 100644 submissions/lab2.md diff --git a/labs/lab2/threagile-model-auth.yaml b/labs/lab2/threagile-model-auth.yaml new file mode 100644 index 000000000..f0e44b170 --- /dev/null +++ b/labs/lab2/threagile-model-auth.yaml @@ -0,0 +1,370 @@ +threagile_version: 1.0.0 + +title: Juice Shop Authentication Flow +date: "2026-06-13" + +author: + name: Your Name + homepage: https://github.com/ratteperk + +management_summary_comment: > + Focused threat model of the JWT-based authentication flow in OWASP Juice Shop. + Covers login, JWT issuance, session management, and admin access control. + +business_criticality: critical + +business_overview: + description: > + Authentication subsystem of OWASP Juice Shop. Handles user login, + JWT token issuance, session management, and role-based admin access. + +technical_overview: + description: > + Browser authenticates via /rest/user/login endpoint. Server validates + credentials against user database, issues JWT signed with private key. + JWT is stored in browser localStorage and sent in Authorization header + for subsequent requests. Admin endpoints verify JWT signature and role. + +questions: + Is JWT signing key stored securely?: "" + Are tokens validated server-side on each request?: "" + Is there token expiration and refresh mechanism?: "" + Is admin role verified server-side on each admin request?: "" + +abuse_cases: + JWT Forgery: > + Attacker forges JWT with admin role using weak or stolen signing key. + Token Theft via XSS: > + Attacker steals JWT from localStorage via XSS vulnerability. + Brute Force Login: > + Attacker attempts repeated login attempts to guess credentials. + SQL Injection on Login: > + Attacker injects SQL via login form to bypass authentication. + +security_requirements: + JWT Signing Key Protection: > + Store JWT signing keys in HSM or vault, not in application config. + Token Expiration: > + Enforce short TTL (15min) and implement refresh token rotation. + Server-Side Validation: > + Validate JWT signature and expiration on every protected request. + Secure Token Storage: > + Use HttpOnly cookies instead of localStorage to prevent XSS theft. + +tags_available: + - auth + - jwt + - nodejs + - browser + - database + - pii + - library + - docker + +data_assets: + + Credentials: + id: credentials + description: "Username + password (hashed with bcrypt)." + usage: business + tags: ["auth", "pii"] + origin: user-supplied + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: critical + availability: operational + justification_cia_rating: > + User credentials must be protected to prevent account takeover. + + JWT Token: + id: jwt-token + description: "JSON Web Token for session authentication." + usage: business + tags: ["auth", "jwt"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: critical + availability: operational + justification_cia_rating: > + JWT tokens grant access to user sessions. Compromise allows session hijacking. + + Signing Key: + id: signing-key + description: "Private key for JWT signing (RSA/ECDSA)." + usage: business + tags: ["auth"] + origin: application + owner: Lab Owner + quantity: few + confidentiality: strictly-confidential + integrity: critical + availability: operational + justification_cia_rating: > + Compromise of signing key allows forging arbitrary JWT tokens with any role. + + Admin Requests: + id: admin-requests + description: "Administrative operations requiring elevated privileges." + usage: business + tags: ["auth"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: > + Admin operations must be protected from unauthorized access. + +technical_assets: + + Browser: + id: browser + description: "End-user web browser (client)." + type: external-entity + usage: business + used_as_client_by_human: true + out_of_scope: false + size: system + technology: browser + tags: ["browser"] + internet: true + machine: virtual + encryption: none + owner: External User + confidentiality: public + integrity: operational + availability: operational + justification_cia_rating: "Client controlled by end user." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: [] + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: + Browser to Auth API: + target: auth-api + description: "Login and registration requests." + protocol: https + authentication: none + authorization: none + tags: [] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - credentials + data_assets_received: + - jwt-token + Browser to Admin Endpoint: + target: admin-endpoint + description: "Authenticated requests with JWT in Authorization header." + protocol: https + authentication: token + authorization: enduser-identity-propagation + tags: [] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - jwt-token + - admin-requests + data_assets_received: [] + + Auth API: + id: auth-api + description: "Authentication API endpoint (/rest/user/login)." + type: process + usage: business + used_as_client_by_human: false + out_of_scope: false + size: application + technology: web-server + tags: ["nodejs", "auth"] + internet: false + machine: container + encryption: none + owner: Lab Owner + confidentiality: internal + integrity: important + availability: important + justification_cia_rating: "Handles authentication logic." + multi_tenant: true + redundant: false + custom_developed_parts: true + data_assets_processed: + - credentials + - jwt-token + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: + Auth to Token Signer: + target: token-signer + description: "Request JWT signing." + protocol: in-process-library-call + authentication: none + authorization: none + tags: [] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - jwt-token + data_assets_received: [] + Auth to User DB: + target: user-db + description: "Validate credentials against database." + protocol: jdbc-encrypted + authentication: credentials + authorization: none + tags: [] + vpn: false + ip_filtered: false + readonly: true + usage: business + data_assets_sent: + - credentials + data_assets_received: [] + + Token Signer: + id: token-signer + description: "JWT signing and verification component." + type: process + technology: library + usage: business + used_as_client_by_human: false + out_of_scope: false + size: component + tags: ["jwt", "auth"] + internet: false + machine: container + encryption: none + owner: Lab Owner + confidentiality: strictly-confidential + integrity: critical + availability: operational + justification_cia_rating: "Handles JWT signing keys." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: + - jwt-token + data_assets_stored: + - signing-key + data_formats_accepted: [] + communication_links: {} + + User DB: + id: user-db + description: "User database (SQLite) storing credential hashes." + type: datastore + usage: business + used_as_client_by_human: false + out_of_scope: false + size: component + technology: database + tags: ["database"] + internet: false + machine: container + encryption: data-with-symmetric-shared-key + owner: Lab Owner + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: "Stores user credentials." + multi_tenant: true + redundant: false + custom_developed_parts: false + data_assets_processed: [] + data_assets_stored: + - credentials + data_formats_accepted: [] + communication_links: {} + + Admin Endpoint: + id: admin-endpoint + description: "Admin API endpoint requiring JWT with admin role." + type: process + usage: business + used_as_client_by_human: false + out_of_scope: false + size: application + technology: web-server + tags: ["nodejs", "auth"] + internet: false + machine: container + encryption: none + owner: Lab Owner + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: "Handles admin operations." + multi_tenant: true + redundant: false + custom_developed_parts: true + data_assets_processed: + - jwt-token + - admin-requests + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: + Admin Verifies JWT: + target: token-signer + description: "Verify JWT signature and extract role." + protocol: in-process-library-call + authentication: none + authorization: none + tags: [] + vpn: false + ip_filtered: false + readonly: true + usage: business + data_assets_sent: + - jwt-token + data_assets_received: [] + +trust_boundaries: + + Internet: + id: internet + description: "Untrusted public network." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - browser + trust_boundaries_nested: + - container + + Container: + id: container + description: "Docker container network." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - auth-api + - token-signer + - user-db + - admin-endpoint + trust_boundaries_nested: [] + +shared_runtimes: + + Docker Container: + id: docker-container + description: "Docker container runtime." + tags: ["docker"] + technical_assets_running: + - auth-api + - token-signer + - user-db + - admin-endpoint \ 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 100755 index 000000000..d79b76ab6 --- /dev/null +++ b/labs/lab2/threagile-model-secure.yaml @@ -0,0 +1,429 @@ +threagile_version: 1.0.0 + +title: Local lab 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 (HTTPS on 3000 internally)." + protocol: https + authentication: session-id + authorization: enduser-identity-propagation + 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 (HTTPS POST) to external WebHook when a challenge is solved. Uses parameterized queries (prepared statements) for database operations." + protocol: https + authentication: token + 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: data-with-symmetric-shared-key + 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/submissions/lab2.md b/submissions/lab2.md new file mode 100644 index 000000000..338cbd637 --- /dev/null +++ b/submissions/lab2.md @@ -0,0 +1,94 @@ +## Task 1: Baseline Threat Model + +### Risk count by severity +| Severity | Count | +|----------|------:| +| Critical | 0 | +| High | 0 | +| Elevated | 4 | +| Medium | 14 | +| Low | 5 | +| **Total** | 23 | + +### Top 5 risks (from risks.json) +1. **unencrypted-communication@user-browser>direct-to-app-no-proxy** — Unencrypted Communication (Direct to App); severity **Elevated**; exploitation Likely/High; affecting user-browser → juice-shop +2. **unencrypted-communication@reverse-proxy>to-app** — Unencrypted Communication (To App); severity **Elevated**; exploitation Likely/Medium; affecting reverse-proxy → juice-shop +3. **missing-authentication@reverse-proxy>to-app** — Missing Authentication; severity **Elevated**; exploitation Likely/Medium; affecting juice-shop +4. **cross-site-scripting@juice-shop** — Cross-Site Scripting (XSS); severity **Elevated**; exploitation Likely/Medium; affecting juice-shop +5. **container-baseimage-backdooring@juice-shop** — Container Base Image Backdooring; severity **Medium**; exploitation Unlikely/Medium; affecting juice-shop + +### STRIDE mapping (Lecture 2 slide 7) +1. **unencrypted-communication (Direct to App)** — **I** (Information Disclosure) — HTTP traffic transfers authentication data (tokens, credentials) in plaintext, allowing network attackers to eavesdrop +2. **unencrypted-communication (proxy→app)** — **I** (Information Disclosure) — Internal proxy-to-app communication lacks encryption, exposing session tokens and product data +3. **missing-authentication** — **E** (Elevation of Privilege) — Reverse proxy forwards requests to Juice Shop without authentication, allowing unauthenticated access to sensitive data +4. **cross-site-scripting** — **T** (Tampering) — XSS allows attackers to inject malicious scripts that steal/modify user sessions and data +5. **container-baseimage-backdooring** — **T** (Tampering) — Compromised base images allow persistent code execution in deployed containers + +### Trust boundary observation +The arrow **User Browser → Juice Shop Application** (Direct to App, HTTP on port 3000) crosses the trust boundary from **Internet** to **Container Network**. This arrow is particularly attractive because: +- It transfers authentication data (Tokens & Sessions) in **plaintext** over HTTP +- It's marked as **Elevated** risk with **Likely** exploitation and **High** impact +- Any network attacker on the same network can perform MITM attacks to steal user credentials and session tokens +- Juice Shop Application has RAA of 70%, making it a high-value target + +--- + +## Task 2: Secure Variant & Diff + +### Risk count comparison +| Severity | Baseline | Secure | Δ | +|----------|---------:|-------:|--:| +| Critical | 0 | 0 | 0 | +| High | 0 | 0 | 0 | +| Elevated | 4 | 2 | **-2** | +| Medium | 14 | 13 | **-1** | +| Low | 5 | 5 | 0 | +| **Total** | 23 | 20 | **-3** | + +### Which rules are GONE in the secure variant? +1. **unencrypted-communication@reverse-proxy>to-app** — Fixed by changing protocol from `http` to `https` for the proxy→app communication link +2. **missing-authentication@reverse-proxy>to-app** — Fixed by adding `authentication: session-id` and `authorization: enduser-identity-propagation` to the proxy→app link +3. **unencrypted-asset@persistent-storage** — Fixed by adding `encryption: data-with-symmetric-shared-key` to the Persistent Storage technical asset + +### Which rules are STILL THERE in the secure variant? +1. **cross-site-scripting@juice-shop** — My changes only addressed transport security (HTTPS) and storage encryption. XSS is an **application-level vulnerability** that requires input validation, output encoding, and CSP headers. Transport encryption doesn't prevent malicious script injection in the application code. + +2. **unencrypted-communication@user-browser>direct-to-app-no-proxy** — This risk remains because the "Direct to App (no proxy)" communication link still uses HTTP. In a real deployment, you would either disable direct access entirely (force all traffic through the reverse proxy) or also upgrade this link to HTTPS. The model keeps both paths for architectural flexibility, so the direct path remains a risk. + +3. **missing-hardening@juice-shop** and **missing-hardening@persistent-storage** — Hardening is an operational concern (CIS benchmarks, vendor guides) that cannot be expressed through YAML model fields. These risks require actual configuration work outside the threat model. + +### Honesty check +Total dropped from 23 to 20 risks (13% reduction, **not** 50%). This shows that **infrastructure hardening** (HTTPS, encryption at rest, authentication on internal links) addresses only a small subset of risks. The remaining 20 risks require: +- **Application-level fixes** (XSS prevention, CSRF tokens, input validation) — 3 risks +- **Architecture changes** (adding identity store, vault, build infrastructure) — 3 risks +- **Operational controls** (WAF, 2FA, hardening guides, container image scanning) — 10 risks +- **Model completeness** (removing unnecessary assets, adding missing components) — 4 risks + +This demonstrates **defense-in-depth**: transport security is necessary but insufficient. You need layered security controls across infrastructure, application, and operations. The cost-benefit analysis shows that infrastructure hardening is relatively cheap (configuration changes) but only addresses 13% of risks. Full mitigation requires expensive application rewrites, architectural changes, and operational processes. + +--- + +## Bonus Task: Auth Flow Threat Model + +### Risk count +| Severity | Count | +|----------|------:| +| Critical | 0 | +| High | 0 | +| Elevated | 5 | +| Medium | 16 | +| Low | 11 | +| **Total** | 32 | + +### Three auth-specific risks (NOT in the baseline model's top 5) + +The baseline top-5 risks were: +1. unencrypted-communication@user-browser>direct-to-app-no-proxy (Elevated) +2. unencrypted-communication@reverse-proxy>to-app (Elevated) +3. missing-authentication@reverse-proxy>to-app (Elevated) +4. cross-site-scripting@juice-shop (Elevated) +5. container-baseimage-backdooring@juice-shop (Medium) + +### Reflection + +Building the focused auth model surfaced implementation-level risks like SQL injection and unguarded admin access that the baseline architecture model missed because it treated authentication as a black box. This confirms that feature-level threat models are essential for revealing application-layer flaws, while architecture-level models are better suited for catching infrastructure risks. Ultimately, this shows that effective threat modeling must be iterative, combining both macro and micro views to achieve true defense-in-depth.