diff --git a/labs/lab2/threagile-model-auth.yaml b/labs/lab2/threagile-model-auth.yaml new file mode 100644 index 000000000..8053a4102 --- /dev/null +++ b/labs/lab2/threagile-model-auth.yaml @@ -0,0 +1,453 @@ +threagile_version: 1.0.0 + +title: Juice Shop Auth Model +date: 2025-09-18 + +author: + name: Student Name + homepage: https://example.edu + +management_summary_comment: > + Focused threat model for the Juice Shop authentication flow. The model keeps + only the assets and links needed to reason about login, JWT issuance, + verification, and admin access. + +business_criticality: important + +business_overview: + description: > + Small authentication-focused model for an OWASP Juice Shop-style system. + The objective is to analyze login, token issuance, protected requests, and + admin access without the noise of the full application architecture. + images: [] + +technical_overview: + description: > + A browser in the Internet trust boundary sends credentials to an auth API in + the container boundary. The auth API asks a token signing component to issue + JWTs, stores user credential data in a user database, and forwards protected + requests to an admin endpoint when a valid token is presented. The model + includes the JWT signing key as a sensitive data asset because compromise of + that key breaks token integrity across the flow. + images: [] + +questions: + Are login requests protected with HTTPS?: "" + Are JWTs signed with a dedicated secret key?: "" + Are admin requests protected by server-side role checks?: "" + +abuse_cases: + Credential Stuffing: > + Attackers try repeated login attempts to guess passwords or reuse leaked credentials. + Token Forgery: > + An attacker attempts to forge or tamper with JWTs to impersonate another user. + Admin Role Abuse: > + A normal user tries to reach admin-only functionality by altering client-side state or token claims. + +security_requirements: + TLS in transit: Require HTTPS for browser-to-API traffic and for all internal auth calls that carry secrets. + Signed tokens: Protect JWT signing keys and verify signatures on every protected request. + Server-side authorization: Check roles on the server before any admin operation is accepted. + Brute-force protection: Rate-limit login attempts and add account lockout or step-up verification where appropriate. + +tags_available: + - auth + - tokens + - pii + - public + - actor + - user + - app + - database + - secret + - session + - admin + - login + - jwt + - container + - internet + - primary + - direct + +# ========================= +# DATA ASSETS +# ========================= +data_assets: + + Credentials: + id: credentials + description: "Username and password submitted by the browser during login or registration." + usage: business + tags: ["auth", "pii"] + origin: user-supplied + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: > + Credentials are highly sensitive because disclosure or tampering enables account compromise. + + JWT Token: + id: jwt-token + description: "Signed access token returned after successful authentication." + usage: business + tags: ["auth", "tokens"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: > + The token is the bearer credential for protected API access. Integrity is critical because a forged or altered token changes the authenticated identity. + + Session State: + id: session-state + description: "Server-side session context, refresh state, or login status cached for the user." + usage: business + tags: ["session", "auth"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: confidential + integrity: important + availability: important + justification_cia_rating: > + Session state binds a user to authenticated behavior and should not be disclosed or manipulated. + + Admin Request: + id: admin-request + description: "Requests that trigger privileged administrative actions." + usage: business + tags: ["admin"] + origin: application + owner: Lab Owner + quantity: many + confidentiality: internal + integrity: critical + availability: important + justification_cia_rating: > + Administrative requests must not be tampered with because they directly control privileged operations. + + JWT Signing Key: + id: jwt-signing-key + description: "Secret used to sign and verify JWTs." + usage: business + tags: ["secret", "tokens"] + origin: application + owner: Lab Owner + quantity: few + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: > + If the signing key is exposed, attackers can mint valid tokens and bypass the authentication boundary entirely. + +# ========================= +# TECHNICAL ASSETS +# ========================= +technical_assets: + + Browser: + id: browser + description: "End-user browser used to log in and call protected endpoints." + 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"] + internet: true + machine: virtual + encryption: none + owner: External User + confidentiality: public + integrity: operational + availability: operational + justification_cia_rating: "Untrusted client in the Internet trust boundary." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: [] + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: + Login and Register: + target: auth-api + description: "Login and registration traffic carrying user credentials." + protocol: https + authentication: none + authorization: none + tags: ["primary"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - credentials + data_assets_received: + - jwt-token + - session-state + Protected API Call: + target: auth-api + description: "Browser sends the JWT in the Authorization header to access protected endpoints." + protocol: https + authentication: session-id + authorization: enduser-identity-propagation + tags: ["direct"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - jwt-token + - admin-request + data_assets_received: + - session-state + - admin-request + + Token Refresh: + target: auth-api + description: "Refresh flow for renewing the user's session state." + protocol: https + authentication: session-id + authorization: enduser-identity-propagation + tags: ["direct"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - jwt-token + - session-state + data_assets_received: + - jwt-token + - session-state + + Auth API: + id: auth-api + description: "Authentication API endpoint that validates credentials and issues tokens." + 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", "auth", "login"] + internet: false + machine: container + encryption: none + owner: Lab Owner + confidentiality: internal + integrity: important + availability: important + justification_cia_rating: "Core authentication service." + multi_tenant: false + redundant: false + custom_developed_parts: true + data_assets_processed: + - credentials + - jwt-token + - session-state + data_assets_stored: + - session-state + data_formats_accepted: + - json + communication_links: + Request JWT Signing: + target: token-service + description: "Auth API asks the token service to sign or verify JWTs." + protocol: https + authentication: credentials + authorization: technical-user + tags: ["primary"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - session-state + data_assets_received: + - jwt-token + Lookup User Record: + target: user-db + description: "Credential lookup against the user store during login." + protocol: jdbc-encrypted + authentication: credentials + authorization: technical-user + tags: ["primary"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - credentials + data_assets_received: + - credentials + Forward Admin Request: + target: admin-endpoint + description: "Authenticated admin request forwarded only after server-side role validation." + protocol: https + authentication: credentials + authorization: technical-user + tags: ["admin"] + vpn: false + ip_filtered: false + readonly: false + usage: business + data_assets_sent: + - admin-request + - jwt-token + data_assets_received: + - admin-request + + Token Service: + id: token-service + description: "JWT signer/verifier responsible for issuing and validating access tokens." + type: process + usage: business + used_as_client_by_human: false + out_of_scope: false + justification_out_of_scope: + size: component + technology: web-service-rest + tags: ["auth", "tokens", "secret"] + internet: false + machine: container + encryption: none + owner: Lab Owner + confidentiality: internal + integrity: critical + availability: important + justification_cia_rating: "Compromise of this component would invalidate all tokens." + multi_tenant: false + redundant: false + custom_developed_parts: true + data_assets_processed: + - jwt-token + - jwt-signing-key + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: + Verify Key Material: + target: user-db + description: "Optional lookup of user or key metadata needed for token validation." + protocol: jdbc-encrypted + authentication: credentials + authorization: technical-user + tags: ["primary"] + vpn: false + ip_filtered: false + readonly: true + usage: business + data_assets_sent: + - jwt-signing-key + data_assets_received: + - session-state + + User DB: + id: user-db + description: "Credential store for user accounts and session-relevant state." + type: datastore + usage: business + used_as_client_by_human: false + out_of_scope: false + justification_out_of_scope: + size: component + technology: database + tags: ["database", "auth"] + internet: false + machine: container + encryption: data-with-symmetric-shared-key + owner: Lab Owner + confidentiality: confidential + integrity: critical + availability: important + justification_cia_rating: "Stores sensitive identity material." + multi_tenant: false + redundant: false + custom_developed_parts: false + data_assets_processed: + - credentials + - session-state + data_assets_stored: + - credentials + - session-state + communication_links: {} + + Admin Endpoint: + id: admin-endpoint + description: "Admin-only endpoint that performs privileged operations after server-side authorization." + type: process + usage: business + used_as_client_by_human: false + out_of_scope: false + justification_out_of_scope: + size: application + technology: web-server + tags: ["admin", "app"] + internet: false + machine: container + encryption: none + owner: Lab Owner + confidentiality: internal + integrity: critical + availability: important + justification_cia_rating: "Privileged endpoint that should only be reachable with a valid admin token." + multi_tenant: false + redundant: false + custom_developed_parts: true + data_assets_processed: + - admin-request + - jwt-token + data_assets_stored: [] + data_formats_accepted: + - json + communication_links: {} + +# ========================= +# TRUST BOUNDARIES +# ========================= +trust_boundaries: + + Internet: + id: internet + description: "Untrusted public network." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - browser + trust_boundaries_nested: [] + + Container: + id: container + description: "Internal application container boundary." + type: network-dedicated-hoster + tags: [] + technical_assets_inside: + - auth-api + - token-service + - user-db + - admin-endpoint + trust_boundaries_nested: [] + +shared_runtimes: + Docker Runtime: + id: docker-runtime + description: "Container runtime hosting the auth services." + tags: ["container"] + technical_assets_running: + - auth-api + - token-service + - user-db + - admin-endpoint + +individual_risk_categories: {} + +risk_tracking: {} diff --git a/labs/lab2/threagile-model-secure.yaml b/labs/lab2/threagile-model-secure.yaml new file mode 100644 index 000000000..22bae8b98 --- /dev/null +++ b/labs/lab2/threagile-model-secure.yaml @@ -0,0 +1,420 @@ +threagile_version: 1.0.0 + +title: OWASP Juice Shop Secure Variant +date: 2025-09-18 + +author: + name: Student Name + homepage: https://example.edu + +management_summary_comment: > + Hardened variant of the Juice Shop lab model. User traffic is HTTPS-only, + internal proxy-to-app traffic is authenticated and encrypted, the persistent + storage volume is encrypted at rest, and the application is documented as + using parameterized queries for database access. Plain-text log persistence is + removed from the app model. + +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 + here is a hardened architectural variant with tighter transport security, storage + encryption, and reduced exposure. + + 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 either directly on + localhost:3000 over HTTPS or via a reverse proxy on ports 80/443 with HTTPS. + The proxy-to-app hop is also encrypted and authenticated. The Juice Shop server + may issue outbound requests to external services (e.g. a configured WebHook for + solved challenge notifications). All application data is stored on the host’s + filesystem via a mounted volume, which is encrypted at rest. 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 + + 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 over TLS with a technical service credential." + protocol: https + authentication: credentials + authorization: technical-user + tags: [] + vpn: false + ip_filtered: true + 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, uses parameterized queries for DB access)." + 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: [] + data_formats_accepted: + - json + communication_links: + To Challenge WebHook: + target: webhook-endpoint + description: "Optional outbound callback to external WebHook when a challenge is solved." + protocol: https + authentication: credentials + 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: + - 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: + 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..7e9400e9d --- /dev/null +++ b/submissions/lab2.md @@ -0,0 +1,75 @@ +# Lab 2 — Submission + +## 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 +1. **cross-site-scripting** — Cross-Site Scripting (XSS) risk at Juice Shop Application; severity Elevated; affecting Juice Shop Application +2. **missing-authentication** — Missing Authentication covering communication link To App from Reverse Proxy to Juice Shop Application; severity Elevated; affecting Juice Shop Application +3. **unencrypted-communication** — Unencrypted Communication named To App between Reverse Proxy and Juice Shop Application; severity Elevated; affecting Reverse Proxy +4. **unencrypted-communication** — Unencrypted Communication named Direct to App (no proxy) between User Browser and Juice Shop Application transferring authentication data (like credentials, token, session-id, etc.); severity Elevated; affecting User Browser +5. **missing-waf** — Missing Web Application Firewall (WAF) risk at Juice Shop Application; severity Low; affecting Juice Shop Application + +### STRIDE mapping +- Risk 1: **T** — XSS tampers with content that the browser executes, which changes the behavior of the page and can manipulate user actions. +- Risk 2: **S** — Missing authentication lets an attacker pretend to be a trusted caller on the proxy-to-app link. +- Risk 3: **I** — Cleartext proxy-to-app traffic can be intercepted and read in transit, exposing sensitive application data. +- Risk 4: **I** — Cleartext direct browser-to-app traffic can leak credentials and session material to anyone who can observe the network path. +- Risk 5: **D** — Without a WAF, the app has less protection against high-volume or automated hostile traffic, especially at the boundary. + +### Trust boundary observation +One high-value boundary-crossing arrow in the top 5 is the direct browser-to-app path from the Internet trust boundary into the container network. It is attractive because authentication data crosses it in cleartext, so an attacker who can observe or influence that path can steal credentials or session material and immediately pivot into the app. + +## Task 2: Secure Variant & Diff + +### Risk count comparison +| Severity | Baseline | Secure | Δ | +|----------|---------:|-------:|--:| +| Critical | 0 | 0 | 0 | +| High | 0 | 0 | 0 | +| Elevated | 4 | 1 | -3 | +| Medium | 14 | 11 | -3 | +| Low | 5 | 5 | 0 | +| **Total** | 23 | 17 | -6 | + +### Which rules are gone in the secure variant? +1. `missing-authentication` — fixed by changing the proxy-to-app and browser-to-app links to HTTPS-only and adding authenticated proxy-to-app traffic. +2. `unencrypted-asset` — fixed by encrypting the persistent storage asset at rest. +3. `unencrypted-communication` — fixed by switching the inbound and outbound links to HTTPS. + + +### Which rules are still there in the secure variant? +1. `cross-site-scripting` — The transport and storage changes do not change the application’s browser-side input handling, so the XSS issue remains. A secure transport layer cannot fix unsafe DOM or template handling. +2. `unnecessary-data-asset` — The model still includes a log data asset, so Threagile continues to flag it as present even though the transport hardening is better. Removing that asset entirely would be a stronger reduction than merely encrypting the path. + +### Honesty check +No. The total did not drop by more than 50%; it dropped from 23 to 17. That means the hardening changes helped, but they mainly removed transport and storage exposure rather than the deeper application-level issues. The cost-benefit is still positive, but eliminating the remaining risks would require more invasive app and edge changes. + +## Bonus Task: Auth Flow Threat Model + +### Risk count +| Severity | Count | +|----------|------:| +| Critical | 0 | +| High | 0 | +| Elevated | 5 | +| Medium | 21 | +| Low | 14 | +| **Total** | 40 | + +### Three auth-specific risks +1. **missing-authentication** — STRIDE: S — Mitigation: Require a real server-side authentication step for login and registration endpoints, and reject any request that cannot prove user identity. Add rate limiting and logging so repeated unauthenticated probes do not become invisible. +2. **sql-nosql-injection** — STRIDE: T — Mitigation: Use parameterized queries consistently, validate all input at the API boundary, and keep the user store behind a narrowly scoped data access layer. The auth path is especially sensitive because a single injection bug can expose every account. +3. **cross-site-scripting** — STRIDE: T — Mitigation: Implement a strict Content Security Policy (CSP), ensure proper contextual output encoding on the Admin Endpoint, and store JWT access tokens in secure, HttpOnly cookies to protect them from client-side script theft. + +### Reflection +Building the focused auth model surfaced identity and token-handling problems that the broader architecture model mostly buried under generic web-app noise, and the latest revision reduced the total risk count from 45 to 40. The smaller model makes it obvious where spoofing and elevation risks live: login, JWT issuance, protected requests, and admin authorization.