Security Compliance in Simple English
Part 2: STRIDE Threat Modeling for SOC 2 and CASA
In Part 1 we looked at ISO 27001, SOC 2, GDPR and CASA. They all ask a similar question: do you know how your system can be attacked, and what did you do about it? STRIDE is a simple way to answer it, and to leave behind the evidence an auditor wants to see.
STRIDE is not required by SOC 2 or CASA. It is a practical method that produces the risk records and secure-design proof they look for.
Table of Contents
- 1. Where STRIDE Fits
- 2. What STRIDE Is
- 3. How to Run a STRIDE Session
- 4. Example 1: Inbox Summarizer
- 5. Example 2: File Sharing App
- 6. Example 3: Payment Webhooks
- 7. Follow One Threat to the End
- 8. Using STRIDE for SOC 2
- 9. Using STRIDE for CASA
- 10. Turning Threats into Evidence
- 11. Common Pitfalls
- 12. Quick Answers
- 13. Takeaways
Where STRIDE Fits
SOC 2 and CASA are the exam. STRIDE is the study plan. You use it early, at design time, to find problems while they are cheap to fix. Then your controls and your records become the answers.
Learn STRIDE
What the six threats are, and how to run a short session with your team.
What it is · How to run it
What STRIDE Is
“Six questions for every part of the system.”STRIDE is a threat modeling checklist from Microsoft. Its name is the first letter of six threat types. For each part of your system you ask: "Could an attacker do this?"
| Letter | Threat | Plain meaning | Example | Typical fix |
|---|---|---|---|---|
| S | Spoofing | Pretending to be someone else | Using a stolen login token | Strong login, MFA, short sessions |
| T | Tampering | Changing data you should not change | Editing a request to change a price | Input checks, signatures, access limits |
| R | Repudiation | Denying you did something | An admin deletes data and no log shows it | Audit logs that cannot be edited |
| I | Information disclosure | Leaking data | An API returns other users' emails | Encryption, access checks, less data |
| D | Denial of service | Making the service unavailable | Flooding the login endpoint | Rate limits, queues, autoscaling |
| E | Elevation of privilege | Getting more access than allowed | A normal user reaches admin features | Role checks on every request |
Each letter breaks one security property: authentication, integrity, accountability, confidentiality, availability, authorization. That makes it easy to link each threat to a control.
↑ Back to contentsHow to Run a Session
“Draw, ask, rank, fix, record.”You do not need special tools. A whiteboard and an hour are enough for the first round.
- Draw a data flow diagram: users, services, databases, and the arrows between them.
- Mark trust boundaries. A boundary is a line where the level of trust changes, such as the internet to your backend, or your backend to a vendor.
- Apply STRIDE to each part. The table below shows which letters usually apply.
- Rank each threat as high, medium or low.
- Fix the threat with a control, or accept it and write down why.
- Record the result and link it to tickets and tests.
Which letters apply to which part
| Part | What it is | STRIDE threats that usually apply |
|---|---|---|
| External entity | A user or another system you do not control | S, R |
| Process | Code that does work, like an API or a worker | S, T, R, I, D, E |
| Data store | A database, a bucket, a cache | T, I, D (and R if it holds logs) |
| Data flow | Data moving between two parts | T, I, D |
A simple risk ranking
| Risk | Meaning | What to do |
|---|---|---|
| High | Easy to attack and a big impact (for example all user data) | Fix before launch |
| Medium | Harder to attack, or a smaller impact | Fix soon, with a date |
| Low | Hard to attack and a small impact | Accept it, and write down why |
Worked Examples
Three small apps with three different shapes. Each one has a diagram, a threat table, and fixes you can copy. A fourth card follows one threat all the way to the evidence.
Gmail summarizer · File sharing · Payment webhooks · One threat end to end
| Example | What it is | Why it is useful to study | Letters you will see most |
|---|---|---|---|
| 1. Inbox Summarizer | Web app that reads Gmail and summarizes it with AI | Needs both SOC 2 and CASA. Has OAuth and AI risks | S, E, I |
| 2. File Sharing App | Users upload files and share links | Storage, untrusted files and links that leave your trust boundary | I, T, D |
| 3. Payment Webhooks | Receives billing events from a payment provider | A public endpoint that trusts outside messages | S, T |
Example 1: Inbox Summarizer
“An app that reads Gmail.”Imagine a web app called Inbox Summarizer. Users connect their Gmail, and the app uses AI to summarize their email. It needs a Gmail restricted scope, so it will need CASA. Business customers will also ask for SOC 2.
Step 1 and 2: draw it and mark the boundary
Step 3 to 5: threats, fixes and ranks
| ID | Part | Type | Threat | Fix | Risk |
|---|---|---|---|---|---|
| T1 | Web API | S | Attacker reuses a stolen session cookie | Secure, HttpOnly and SameSite cookies, new session ID at login, server-side revocation, idle timeout (MFA at login does not stop a stolen cookie) | Medium |
| T2 | Web API | E | A user changes an ID in the URL and reads another user's summaries | Check the owner on every request, add a test | High |
| T3 | Database | I | Gmail refresh tokens leak from the database or a backup | Encrypt tokens with a managed key, limit DB access, never log tokens | High |
| T4 | Database | T | Someone edits summary rows directly | Least-privilege DB roles, audit trail, approved changes only | Medium |
| T5 | Web API | R | An admin reads a user's data and no record exists | Log every admin action in append-only storage. | Medium |
| T6 | Web API | D | A flood of requests uses up the server and the AI budget | Per-user rate limits, a queue, budget alerts | Medium |
| T7 | Gmail API flow | S | A fake redirect steals the OAuth code | Exact redirect allowlist, state value, PKCE | High |
| T8 | Web API + AI | T, I | Text inside an email tricks the AI into leaking data | Treat email text as untrusted, give the model only that user's data, limit the tools it can call, do not auto-render model-written links or images, ask the user to confirm actions | High |
Look at how the table reads like a to-do list. Every row has a fix and a rank. That is exactly what an auditor wants: risks that are found, rated and followed to the end.
↑ Back to contentsExample 2: File Sharing App
“Untrusted files and shared links.”A team app where people upload files and share them with a link. The new risk here is untrusted files and links that leave your system.
The dashed line is the trust boundary. A person who opens a shared link is outside it, so if a setting is wrong, every file they can reach is exposed.
| ID | Part | Type | Threat | Fix | Risk |
|---|---|---|---|---|---|
| D1 | Object storage | I | A public bucket or guessable file URLs expose private files | Private bucket by default, short-lived signed URLs, random file IDs | High |
| D2 | Web API | E | A viewer-role user calls the delete or share endpoint | Role check for each action, one test per role | High |
| D3 | Object storage | T | Someone uploads a malicious file (malware, or HTML that runs script when opened) | Check type by content, serve files from a separate domain with Content-Disposition: attachment and X-Content-Type-Options: nosniff, run the scan worker | High |
| D4 | Scan worker | D | A huge file or zip bomb uses up the worker | Size limits, timeouts, a sandboxed worker | Medium |
| D5 | Signed link | I | A link is forwarded and a stranger opens it | Expiry time, optional login, view history | Medium |
| D6 | Web API | R | A user shares a file outside the company and denies it | Log every share with user, time and recipient | Medium |
| D7 | Scan worker | E | A parser bug lets a file reach the worker's cloud permissions | Least-privilege role, no network except storage | Medium |
What is different from Example 1
- The big risks are information disclosure (a wrong link or bucket setting) and tampering (a bad file).
- One config setting (a public bucket) can break everything. Put the setting and a check for it in your evidence.
- For CASA, uploads fall under data validation: limit them to expected file types, and make sure uploaded content cannot run by itself.
Example 3: Payment Webhooks
“A public endpoint that must be trusted.”Your app receives events from a payment provider, such as "invoice paid". The endpoint is public, and you must trust what arrives. This is a small system, but spoofing and replay are classic problems.
The red dashed arrow is an attacker pretending to be the payment provider. The only thing that tells the two senders apart is the signature, which the endpoint checks with the signing secret.
| ID | Part | Type | Threat | Fix | Risk |
|---|---|---|---|---|---|
| W1 | Webhook | S | An attacker posts a fake "payment succeeded" event | Verify the provider's signature on the raw body, with the provider's library or a timing-safe compare | High |
| W2 | Webhook | T | The event body is changed on the way | Signature over the exact bytes, HTTPS only | High |
| W3 | Webhook | T | An old valid event is sent again (replay) | Check the timestamp, store event IDs, ignore duplicates. Events can also arrive out of order, so check the current state | Medium |
| W4 | Billing | E | An event for account A upgrades account B | Find the account from the stored provider customer ID, not from free text | High |
| W5 | Webhook | I | The signing secret ends up in code or logs | Secrets manager, rotation, never log the signing secret | High |
| W6 | Queue | D | An event flood or retry storm | Reply fast, queue the work, add a dead-letter queue | Medium |
| W7 | Billing | R | A plan changes and nobody can say why | Save the event ID with every plan change | Medium |
What is different from Example 1
- There are no user logins here. The proof of who is calling is a signature, so spoofing (S) is about the signature check.
- The rule of thumb: do not act on an event you did not verify.
- For SOC 2 this supports CC6 (access) and CC7 (monitoring). Failed signature checks are a good alert.
- CASA has no webhook-specific section, so follow your provider's own webhook guide.
Follow One Threat to the End
“From the model to the proof.”A threat model is only useful if the fix is proven. Here is one row, T2 from Example 1, followed from the model to the evidence. In T2 a user changes an ID in the URL and reads another user's summary. Security people call this an IDOR (insecure direct object reference).
| Step | What you do | What you save (evidence) |
|---|---|---|
| 1. Threat | Row T2 in the threat model, rated High | The threat model file, with date and owner |
| 2. Ticket | Create SEC-114 with a clear done condition | Link to the ticket |
| 3. Fix | Pull request with a code review and approval | Link to the merged PR and its approval |
| 4. Test | Add an automated test that runs in CI | Link to the CI run that passes |
| 5. Record | Mark T2 as done in the model with the links | Updated model and review log entry |
The fix
// Before: any signed-in user can read any summary by guessing the ID
app.get('/summaries/:id', auth, async (req, res) => {
res.json(await db.summaries.findById(req.params.id));
});
// After: the query is limited to the signed-in user's own rows
app.get('/summaries/:id', auth, async (req, res) => {
const row = await db.summaries.findOne({
id: req.params.id,
ownerId: req.user.id,
});
if (!row) return res.status(404).end(); // same answer for "missing" and "not yours"
res.json(row);
});
The test
test('owner can read a summary, another user cannot', async () => {
const summary = await createSummary(userA);
const own = await api.as(userA).get(`/summaries/${summary.id}`);
expect(own.status).toBe(200);
expect(own.body.id).toBe(summary.id);
const other = await api.as(userB).get(`/summaries/${summary.id}`);
expect(other.status).toBe(404);
});
The code returns the same 404 for "not found" and "not yours", so an attacker cannot learn which IDs exist. The test has two halves on purpose: the first proves the endpoint works for the owner, so a route that returns 404 for everyone cannot pass.
Where this one threat counts
| Framework | Where this one threat counts |
|---|---|
| SOC 2 | CC3.2 (risk found and rated), CC6.3 (least privilege), CC8.1 (reviewed change) |
| CASA | Access control (IDOR). Your test is supporting evidence. The lab runs its own test cases, and under AL1 you submit evidence for each one |
| ISO 27001 | Access control and secure development controls |
| GDPR | Article 32 security, and Article 25 Privacy by Design: users cannot see other people's data |
One small row gave you proof for three or four frameworks. Do this for every high-risk threat and your evidence folder fills up with real, dated records.
↑ Back to contentsUse It for SOC 2 and CASA
Map each threat to the controls and tests that auditors and labs expect, and keep the proof.
SOC 2 · CASA · Evidence
Using STRIDE for SOC 2
“Show that you find and rate risks.”SOC 2 does not ask for STRIDE. It asks whether you identify and assess risks (CC3). In a Type II report, the auditor then tests whether your controls worked over the whole period. A threat model does not replace the company-wide risk assessment, which auditors usually expect as a risk register that management reviews every year. But it is the detailed input to that register, and every STRIDE letter points to controls you already need.
| STRIDE | SOC 2 criteria it supports | What an auditor may ask to see |
|---|---|---|
| S Spoofing | CC6.1, CC6.2 (logical access) | MFA settings, SSO setup, the user list |
| T Tampering | CC6.1, CC6.7 (data in transit), CC8.1 (change management) | Branch protection, code review records, TLS settings |
| R Repudiation | CC7.2, CC7.3 (monitoring and evaluating events) | Log samples, alert rules, retention policy |
| I Info disclosure | CC6.1, CC6.7, C1.1 (if Confidentiality is in scope) | Encryption settings, key management, data classes |
| D Denial of service | A1.1, A1.2 (if Availability is in scope), CC6.6 (threats from outside) | Rate-limit config, capacity monitoring, recovery tests |
| E Elevation of privilege | CC6.1, CC6.3 (roles and least privilege) | Role definitions, access review records |
Where the threat model itself is evidence
| SOC 2 area | How the threat model helps |
|---|---|
| CC3.2 Identify and analyze risks | Feeds your company risk register. The threat models are the detailed input for your software risks. |
| CC3.4 Assess changes that affect risk | Update it when the design changes, such as a new vendor or a new data type. |
| CC8.1 Change management | Each major change has a short threat review linked in the pull request. |
| CC5.1 Control activities that mitigate risks | Each high risk has an owner, a fix and a date. |
Criteria numbers follow the 2017 Trust Services Criteria. Only the Security criteria (the common criteria, CC) are always in scope. The A1 (Availability) and C1 (Confidentiality) rows apply only if you chose those categories. Confirm the mapping with your auditor, because each firm tests slightly different things.↑ Back to contents
Using STRIDE for CASA
“Fix it before the lab finds it.”CASA does not ask for STRIDE either, and its own v2 specification has no threat-modeling requirement. (OWASP ASVS, which CASA builds on, does ask for threat modeling at its higher levels.) The lab tests your app against the CASA specification. The best way to pass is to find and fix those problems before the lab does, and a threat model is a good way to do that.
The table maps each STRIDE letter to the CASA areas. Notice that CASA is narrower than STRIDE: it says little about audit logging or denial of service, so Repudiation and Denial of service matter more for SOC 2 than for CASA.
| STRIDE | CASA area | What to test before the lab does |
|---|---|---|
| S Spoofing | Authentication, Session management, OAuth rules | Login limits, cookie flags (Secure, HttpOnly), logout, OAuth redirect_uri and state, PKCE |
| T Tampering | Data validation, Access control, Token protection | Injection and XSS tests, uploads, forged or replayed tokens |
| R Repudiation | Logging rules (no credentials in logs) | Logs never contain passwords or tokens. (Audit trails are a SOC 2 matter) |
| I Info disclosure | Communications, Server-side secrets, No tokens in URLs | TLS settings, secret storage, token encryption, no sensitive data in URLs |
| D Denial of service | Brute-force resistance, Anti-automation | Login rate limits. (Wider availability is a SOC 2 matter) |
| E Elevation of privilege | Access control: least privilege, IDOR, admin MFA | Owner checks, role checks, IDOR tests, MFA on admin pages |
How to use it for CASA
- Run the STRIDE session for the app, with the Google data flow on the diagram.
- Use the table above to turn each high-risk threat into a test.
- Run your own scans and tests. Fix the findings.
- Keep the reports. Under AL1 you hand your evidence to the lab. Under AL2 the lab tests the app itself. Keep everything for the renewal, which is at least every 12 months.
CASA is updated from time to time. Check the current spec and the assurance level Google gives your app before you plan.↑ Back to contents
Turning Threats into Evidence
“If it is not written down, it did not happen.”A threat model on a shared drive proves little. Auditors want to see the whole chain: threat, ticket, fix, test, proof.
| Save this | Why | SOC 2 | CASA |
|---|---|---|---|
| The threat model document, with a date and an owner | Shows you assess risks on purpose | CC3 | Not required by CASA |
| Tickets for each threat, linked to the fix | Shows risks are followed to the end | CC3, CC5 | Fixes before the LOA |
| Pull requests with review and a security note | Shows change management | CC8 | Validation and configuration |
| Test results (scans, IDOR tests, pen test) | Shows the fix works | CC4, CC7 | AL1 evidence |
| Config exports with timestamps (MFA, TLS, encryption). Screenshots only as a backup | Type II samples across the whole period, so one undated screenshot proves little | CC6 | Access control, communications |
| Review log: when you re-checked the model | Shows the process repeats | CC3.4, CC4 | Yearly renewal |
A folder layout that keeps evidence easy to find
security/
├── threat-models/
│ ├── inbox-summarizer-2026-10.md (the model above)
│ └── diagrams/
│ └── inbox-summarizer-dfd.png
├── evidence/
│ ├── 2026-10-mfa-settings.png
│ ├── 2026-10-idor-test-report.pdf
│ └── 2026-11-casa-scan-report.pdf
└── reviews/
└── review-log.md (dates of every re-check)
A template for the threat model file
# Threat model: Inbox Summarizer
Owner: <name> Date: 2026-10-25 Next review: 2027-04-25
Scope: web app, API, database, Gmail API flow
## Diagram
(link to the data flow diagram, with trust boundaries)
## Threats
| ID | Part | STRIDE | Threat | Fix | Risk | Ticket | Status |
|----|----------|--------|------------------------------|------------------------------|------|----------|--------|
| T2 | Web API | E | User reads another's summary | Owner check on every request | High | SEC-114 | Done |
## Accepted risks
- <risk>: <why we accept it>, approved by <name> on <date>
## Review log
- 2026-10-25: first version
Common Pitfalls
- Doing it once and forgetting it. SOC 2 Type II looks at a whole period. Review the model after major changes and at least yearly.
- A model with no owner. Every threat needs a person and a ticket.
- Listing threats but not fixing them. The auditor will pick a few rows and ask for the proof.
- Only the happy path. Include vendors, admin tools, backups, logs and CI/CD. Attackers use those too.
- Treating STRIDE as a replacement for testing. It finds design problems. You still need scans and tests.
- Forgetting AI-specific threats. If an AI model reads untrusted text, add prompt injection to the model, as in T8 above.
Quick Answers
| Question | Answer |
|---|---|
| Is STRIDE required by SOC 2 or CASA? | No. Neither names it. It is one good way to meet their risk and secure-design needs. |
| How long does a session take? | A short meeting with a developer, someone who knows security, and the product owner. |
| When do I run it? | At design time, before big changes, and at least once a year. |
| Does it replace a pen test? | No. The model finds design problems. A pen test and the CASA scan find implementation bugs. |
| Does it cover privacy? | Only partly. Privacy threats need their own method, such as LINDDUN. |
Takeaways
- STRIDE is an internal design tool. SOC 2 and CASA are how others check your work.
- The loop is: draw, apply STRIDE, rank, fix, record.
- Each STRIDE letter maps to controls that SOC 2 criteria and CASA requirements already ask for.
- The value is in the evidence chain: threat, ticket, fix, test, proof.
- Start small. One feature, one hour, one table. Then repeat it with each major change.