|
1
|
--- |
|
2
|
name: threat_modeling |
|
3
|
description: Perform structured threat modeling for a project and write the result to threat_model.md. |
|
4
|
--- |
|
5
|
|
|
6
|
# Threat Modeling Skill |
|
7
|
|
|
8
|
Analyze a project's architecture and produce a security reference document that describes assets, trust boundaries, applicable threat categories, and the security guarantees the project must uphold. |
|
9
|
|
|
10
|
## When to Use |
|
11
|
|
|
12
|
- New project kickoff or initial architecture review |
|
13
|
- A new feature introduces authentication, data storage, network exposure, or third-party integrations |
|
14
|
- Pre-deploy or pre-launch security review |
|
15
|
- The user explicitly asks for a threat model or security analysis |
|
16
|
- After a significant architectural change (new microservice, new database, new external API) |
|
17
|
|
|
18
|
## When NOT to Use |
|
19
|
|
|
20
|
- Cosmetic or UI-only changes with no security surface |
|
21
|
- Pure refactors that do not change trust boundaries, data flows, or access control |
|
22
|
- One-off bug fixes unrelated to security |
|
23
|
|
|
24
|
## Methodology |
|
25
|
|
|
26
|
Use a lightweight STRIDE-inspired approach. Work through these steps in order: |
|
27
|
|
|
28
|
### Step 1: Understand the System |
|
29
|
|
|
30
|
Read the codebase, `replit.md`, and any existing `threat_model.md`. Identify: |
|
31
|
|
|
32
|
- What the application does and who its users are |
|
33
|
- The tech stack (language, framework, database, hosting) |
|
34
|
- External services and integrations (payment providers, auth providers, APIs, object storage) |
|
35
|
- A small amount of reusable scan context: likely production entry points, highest-risk code areas, major public/authenticated/admin boundaries, and whether major directories are production, shared, or dev-only |
|
36
|
|
|
37
|
### Step 2: Enumerate Assets |
|
38
|
|
|
39
|
Assets are anything worth protecting. Common examples: |
|
40
|
|
|
41
|
- **User credentials** -- passwords, tokens, session cookies, API keys |
|
42
|
- **Personal data** -- email addresses, names, payment info, uploaded files |
|
43
|
- **Application secrets** -- database connection strings, signing keys, third-party API keys |
|
44
|
- **Business data** -- orders, invoices, analytics, proprietary content |
|
45
|
|
|
46
|
### Step 3: Map Trust Boundaries |
|
47
|
|
|
48
|
A trust boundary exists wherever data crosses between different levels of trust. Identify: |
|
49
|
|
|
50
|
- **Client / Server boundary** -- browser or mobile app to backend API |
|
51
|
- **Server / Database boundary** -- application code to data store |
|
52
|
- **Server / External Service boundary** -- your backend calling third-party APIs |
|
53
|
- **Public / Authenticated boundary** -- routes or resources that require auth vs. those that don't |
|
54
|
- **User / Admin boundary** -- privilege separation between roles |
|
55
|
- **Internal / Production boundary** -- dev/staging environments vs. production |
|
56
|
|
|
57
|
### Step 4: Walk Through Threat Categories |
|
58
|
|
|
59
|
For each asset and trust boundary, consider these STRIDE categories: |
|
60
|
|
|
61
|
**Spoofing** -- Can an attacker impersonate a legitimate user or service? |
|
62
|
|
|
63
|
- Weak or missing authentication on API endpoints |
|
64
|
- Predictable session tokens or JWTs with no signature verification |
|
65
|
- No origin validation on webhooks or callbacks |
|
66
|
|
|
67
|
**Tampering** -- Can an attacker modify data they shouldn't? |
|
68
|
|
|
69
|
- Missing input validation on form fields, query params, or request bodies |
|
70
|
- Client-side-only enforcement of business rules (price, quantity, permissions) |
|
71
|
- Unsigned or unverified data passed between services |
|
72
|
|
|
73
|
**Repudiation** -- Can a user deny performing an action with no way to prove otherwise? |
|
74
|
|
|
75
|
- Missing audit logs for sensitive operations (payments, account changes, data deletion) |
|
76
|
- Logs that don't capture the acting user or timestamp |
|
77
|
- No integrity protection on log storage |
|
78
|
|
|
79
|
**Information Disclosure** -- Can an attacker access data they shouldn't see? |
|
80
|
|
|
81
|
- PII or secrets appearing in logs, error messages, or API responses |
|
82
|
- Overly broad database queries returned directly to the client |
|
83
|
- Directory listings, stack traces, or debug endpoints exposed in production |
|
84
|
- Missing encryption at rest or in transit |
|
85
|
|
|
86
|
**Denial of Service** -- Can an attacker degrade or disrupt the service? |
|
87
|
|
|
88
|
- No rate limiting on authentication or public API endpoints |
|
89
|
- Unbounded file uploads or request body sizes |
|
90
|
- Resource-intensive operations triggered by unauthenticated users |
|
91
|
- Missing timeouts on external service calls |
|
92
|
|
|
93
|
**Elevation of Privilege** -- Can an attacker gain access beyond their authorized level? |
|
94
|
|
|
95
|
- Missing authorization checks after authentication (IDOR, broken function-level access control) |
|
96
|
- Role checks only on the frontend, not enforced server-side |
|
97
|
- SQL injection, command injection, or template injection leading to arbitrary code execution |
|
98
|
- Path traversal allowing file system access outside intended directories |
|
99
|
- Insecure deserialization allowing object manipulation |
|
100
|
|
|
101
|
### Step 5: Describe Required Guarantees |
|
102
|
|
|
103
|
For each relevant threat, describe the security guarantee the project must uphold. Write these as declarative statements: |
|
104
|
|
|
105
|
- "All API endpoints that access user data MUST require a valid session token." |
|
106
|
- "User passwords MUST be hashed with bcrypt (cost >= 12) and MUST NOT appear in logs." |
|
107
|
- "File uploads MUST be validated for type and size, and MUST be stored outside the web root." |
|
108
|
- "All database queries MUST use parameterized statements." |
|
109
|
|
|
110
|
## What to Look Out For |
|
111
|
|
|
112
|
These are the most common and dangerous patterns. Flag them whenever you encounter them: |
|
113
|
|
|
114
|
**Broken access control** -- Missing auth checks on routes, IDOR (guessable IDs granting access to other users' data), privilege escalation through parameter manipulation, admin functionality reachable by regular users. |
|
115
|
|
|
116
|
**Injection** -- SQL queries built with string concatenation, shell commands constructed from user input, template injection through unsanitized variables, path traversal via user-supplied file names, unsafe deserialization of user-controlled data. |
|
117
|
|
|
118
|
**Cryptographic failures** -- Hardcoded secrets or API keys in source code, secrets committed to git, weak hashing algorithms (MD5, SHA1 for passwords), plaintext storage or logging of PII, missing HTTPS enforcement. |
|
119
|
|
|
120
|
**Security misconfiguration** -- Debug mode enabled in production, CORS set to `*` or overly permissive, default credentials left in place, verbose error messages exposing internals, permissive Content Security Policy. |
|
121
|
|
|
122
|
**SSRF and open redirects** -- User-controlled URLs fetched server-side without allowlist validation, redirect targets taken from query parameters without validation. |
|
123
|
|
|
124
|
**Dependency vulnerabilities** -- Outdated packages with known CVEs, no lockfile or pinned versions, dependencies pulled from untrusted registries. |
|
125
|
|
|
126
|
**Data exposure** -- PII in application logs, overly broad API responses returning fields the client doesn't need, missing rate limiting allowing data scraping, no encryption at rest for sensitive data. |
|
127
|
|
|
128
|
## Output: `threat_model.md` |
|
129
|
|
|
130
|
You MUST write the completed threat model to `threat_model.md` in the project root. If the file already exists, update it in place rather than overwriting unrelated sections. |
|
131
|
|
|
132
|
`threat_model.md` is a **project-level security reference document**, not a tracker. It describes the system, its security-relevant architecture, and the guarantees it must uphold. Another agent will read this file to inform its security decisions -- write it for that audience. |
|
133
|
|
|
134
|
Use the following structure: |
|
135
|
|
|
136
|
```markdown |
|
137
|
# Threat Model |
|
138
|
|
|
139
|
## Project Overview |
|
140
|
|
|
141
|
Brief description of what the application does, its tech stack, and its users. |
|
142
|
|
|
143
|
## Assets |
|
144
|
|
|
145
|
What is worth protecting in this project. Describe each asset category and why it matters. |
|
146
|
|
|
147
|
## Trust Boundaries |
|
148
|
|
|
149
|
Where data crosses between different trust levels. Describe each boundary and what it separates. |
|
150
|
|
|
151
|
## Scan Anchors |
|
152
|
|
|
153
|
A short list of reusable pointers for future security analysis: |
|
154
|
- Production entry points, preferably with concrete file or directory paths when known |
|
155
|
- Highest-risk code areas, preferably with concrete packages, route files, or service directories when known |
|
156
|
- Public vs authenticated vs admin surfaces |
|
157
|
- Dev-only areas that should usually be ignored unless proven reachable in production |
|
158
|
|
|
159
|
Keep this section brief. It should store just enough concrete context to speed up future security scans without turning the threat model into a full repo inventory. |
|
160
|
|
|
161
|
If project context already exists in `replit.md` (project README) or `.agents/memory/` (agent memory), don't repeat the same information. |
|
162
|
|
|
163
|
## Threat Categories |
|
164
|
|
|
165
|
For each STRIDE category that is relevant to this project, write a short narrative: |
|
166
|
- What the threat is in the context of this specific project |
|
167
|
- Why it matters here (what could go wrong) |
|
168
|
- What guarantees are required to address it |
|
169
|
|
|
170
|
Omit categories that genuinely do not apply. Do not pad with generic boilerplate. |
|
171
|
``` |
|
172
|
|
|
173
|
### Example: E-commerce App |
|
174
|
|
|
175
|
```markdown |
|
176
|
# Threat Model |
|
177
|
|
|
178
|
## Project Overview |
|
179
|
|
|
180
|
A Node.js/Express e-commerce application with a React frontend, PostgreSQL database, |
|
181
|
and Stripe integration for payments. Users can browse products, create accounts, |
|
182
|
and purchase items. Deployed on Replit with Replit Auth for user authentication. |
|
183
|
|
|
184
|
## Assets |
|
185
|
|
|
186
|
- **User accounts and sessions** -- email addresses, hashed passwords, session tokens. |
|
187
|
Compromise allows impersonation and access to order history and saved payment methods. |
|
188
|
- **Payment data** -- Stripe customer IDs and tokenized payment references. The app never |
|
189
|
stores raw card numbers, but Stripe tokens could be used to initiate charges. |
|
190
|
- **Order data** -- order history, shipping addresses, item quantities and prices. |
|
191
|
Contains PII and business-sensitive pricing information. |
|
192
|
- **Application secrets** -- Stripe API keys, database connection string, session signing key. |
|
193
|
Compromise of Stripe secret key allows arbitrary charges. |
|
194
|
|
|
195
|
## Trust Boundaries |
|
196
|
|
|
197
|
- **Browser to API** -- all client requests cross this boundary. The API must authenticate |
|
198
|
and authorize every request; the client is untrusted. |
|
199
|
- **API to PostgreSQL** -- the API server has direct database access. SQL injection at the |
|
200
|
API layer would give an attacker full database access. |
|
201
|
- **API to Stripe** -- the server calls Stripe's API with a secret key. SSRF or key leakage |
|
202
|
would allow unauthorized payment operations. |
|
203
|
- **Authenticated to Unauthenticated** -- product browsing is public; cart, checkout, and |
|
204
|
account pages require authentication. The boundary must be enforced server-side. |
|
205
|
|
|
206
|
## Threat Categories |
|
207
|
|
|
208
|
### Spoofing |
|
209
|
|
|
210
|
Users authenticate via Replit Auth. The application must validate the authentication |
|
211
|
token on every request to protected endpoints. Session tokens must be unpredictable |
|
212
|
and expire within a reasonable window. Webhooks from Stripe must be verified using |
|
213
|
Stripe's webhook signature mechanism. |
|
214
|
|
|
215
|
### Tampering |
|
216
|
|
|
217
|
Product prices and order totals must be calculated server-side. The client sends a cart |
|
218
|
(product IDs and quantities) but the server must look up current prices from the database. |
|
219
|
Accepting client-supplied prices would allow purchasing items for arbitrary amount(s). |
|
220
|
|
|
221
|
### Information Disclosure |
|
222
|
|
|
223
|
API responses for order history must be scoped to the authenticated user. The /api/orders |
|
224
|
endpoint must filter by user ID server-side. Error responses must not include stack traces |
|
225
|
or database error details. Stripe API keys must never appear in client-side code or logs. |
|
226
|
|
|
227
|
### Elevation of Privilege |
|
228
|
|
|
229
|
Admin routes (product management, order fulfillment) must check for an admin role |
|
230
|
server-side. All database queries must use parameterized statements to prevent SQL |
|
231
|
injection. File upload endpoints (product images) must validate file type and size. |
|
232
|
``` |
|
233
|
|
|
234
|
### Key Principles |
|
235
|
|
|
236
|
- Be specific to the project. Generic boilerplate like "use HTTPS" is not useful unless the project is actually missing it. |
|
237
|
- Write declaratively. Describe what the system is, what its threats are, and what guarantees it requires. |
|
238
|
- Omit irrelevant categories. If the project has no file uploads, do not write about file upload threats. |
|
239
|
- Keep it concise. This is a reference document, not an essay. A smart agent will reason from it. |
|
240
|
- Keep `## Scan Anchors` brief. It should speed up future security scans without turning the threat model into a repo inventory. |