A Risk Model for Cyber Security: What Should You Protect First?
A practical approach to moving security work out of random tool-trying and into a measurable risk model.
A Risk Model for Cyber Security: What Should You Protect First?
Good security work starts not with choosing the most expensive tool but with understanding what is actually critical. Any checklist made without measuring a system's attack surface is incomplete, because the same vulnerability can produce completely different risks in two different organisations.
This guide brings concepts like threat model, trust boundary, asset inventory, risk register, and mitigation workflow together into a single working flow. The goal is not a "book of quotes" but a system you can wire into weekly automation.
Why Do You Need a Risk Model?
A risk model combines technical findings with business impact. A finding from a test should not stay as a "critical" label; it should be clear which asset it affects, which data it grants access to, what preconditions it requires to exploit, and what the attacker gains from it.
That is why the starting questions are simple:
- Which assets are exposed to the outside world?
- Which systems carry identity, payment, customer data, or production access?
- Which team owns which service?
- What is the business impact if a service goes down?
- Do logging, alerting, and the response process actually work?
The answers to these questions move the security budget and testing time to the right place. Keeping the answers written down is about seeing where a new finding three months from now fits in the same table.
Threat Model: A Four-Step Approach
A simple but sufficient threat model is built like this:
+----------------+ +----------------+ +----------------+
| 1. Assets | --> | 2. Flows | --> | 3. Trust bounds|
+----------------+ +----------------+ +----------------+
|
v
+-------------------------+
| 4. Threats (STRIDE) |
+-------------------------+STRIDE categories:
| Category | Example question |
|---|---|
| Spoofing | Is the sender of this request really that user? |
| Tampering | Can the request be changed in transit? |
| Repudiation | Is proof of who performed this action recorded? |
| Information disclosure | Does the response leak more data than necessary? |
| Denial of service | Can the service be easily saturated? |
| Elevation of privilege | Can a low-privilege user gain high privilege? |
Assess the relevant categories for each data flow; do not force a "no" answer. For example, in an invoice export flow, the threat is an ordinary member obtaining sensitive data under a different tenant identity. The precondition is valid membership, the boundary crossed is tenant scope, and the control is object and operation authorisation on the server. The existence of the control is a claim; a negative test run with two artificial tenants is the evidence that tests that claim.
Trust Boundaries: No Model Without Boundaries
Boundaries for a typical web service:
[public internet]
| boundary A: authentication and rate limit
v
[edge / WAF]
| boundary B: internal network
v
[app server] -- boundary C --> [DB / secret store]
|
| boundary D: üçüncü taraf API
v
[payment / SMTP / analytics]Each boundary should have a control in front of it and a record behind it:
- Boundary A: WAF rule, mTLS, or rate limit.
- Boundary B: network segmentation, security group.
- Boundary C: a least-privilege DB user, audit log.
- Boundary D: API key rotation, signed webhook verification.
The more boundaries, the more complex the model; every new boundary adds a new "who can do what here" question.
Asset Inventory: The Map of Security Work
If the asset inventory is not current, the security team works in the dark. Domain names, subdomains, cloud accounts, API endpoints, third-party integrations, and development environments should be tracked in the same table.
Even for a small team, these fields provide a sufficient start:
| Field | Why it matters |
|---|---|
| Service name | Clarifies ownership and scope |
| Environment | Shows the production, staging, and test split |
| Data type | Indicates the risk of personal data, tokens, or financial data |
| Owning team | Speeds up the remediation process |
| Criticality | Sets testing priority |
| Last review date | Prevents blind spots from forming |
Keep the inventory not as a static document but as CI/CD output. When a new service comes up, its row is added automatically; a deleted service's row is closed.
An example inventory row:
service: billing-api
env: prod
data: cardholder_tokens
owner: payments
criticality: high
last_reviewed: 2026-09-30
internet_exposed: trueRisk Register: Context, Not Just Findings
Each risk register row should carry these fields:
| Field | Description |
|---|---|
| Asset | Which system it touches |
| Data class | PII, financial, identity, internal |
| Threat path | The path the attacker follows |
| Precondition | Auth, internal network, user interaction |
| Impact | Which business loss |
| Existing control | How much is in place |
| Target control | What should be added |
| Owner | Name or team |
| Due date | ISO date |
This table makes risks that are "important but unowned" visible. An unowned row is the name of the next incident.
Prioritisation
It is not possible to close all findings at the same speed. So it is healthier to evaluate findings on three axes:
- Impact: which data or privilege does a successful exploit affect?
- Likelihood: how hard are the attacker's preconditions?
- Detectability: can the existing logging and alerting catch this?
For example, a low-impact misconfiguration reachable only from the internal network should not be scheduled together with an internet-exposed authentication bypass. A good programme closes the path with the highest business impact first.
A simple priority matrix:
Impact
^
| [act now] [priority 1]
| [monitor_record] [priority 2]
+-------------------> LikelihoodIf detectability is low, adding logging is a cheap win even when the priority is low.
Produce Measurable Output
A security report should not be only a list of findings. A manageable security programme produces these outputs:
- A list of critical assets
- The scope of internet-exposed services
- A repeatable test plan
- An owning team and target date for each finding
- Evidence of closed risks
- A summary of recurring root causes
This structure brings penetration testing, bug bounty, code review, and cloud security work together in the same risk language.
Detection and Mitigation Workflow
A typical finding-closure flow:
[Finding] -> [Score risk] -> [Assign owner] -> [Fix] -> [Re-test] -> [Closure]
|
+-- [Interim monitoring: add log/alert]A practical rule for the alerting side: log every privilege grant event, every outbound data flow, and every admin panel access. These three catch most incidents early. To prevent alert fatigue, give every rule a "weekly sample" review.
Windows like a 30-day hot period and a one-year archive can only be example policy, not a rule for every organisation. Set the retention period by the review requirement, the data class, and the applicable legal obligation. A KVKK/VERBİS registration alone cannot assign a common one-year period to all security logs. Access and end-of-period deletion belong in the risk record as much as retention does.
Version Differences: Risk Models
- STRIDE: for categorising threats; suitable for microservice boundaries.
- DREAD: for scoring risk; rarely used in modern teams because it is considered subjective, but it helps in fast prioritisation.
- CVSS v3.1: vulnerability score; exploitability, scope, confidentiality/integrity/availability.
- CVSS v4.0: has Base, Threat, Environmental, and Supplemental groups; the Supplemental group does not change the final score. The FIRST specification does not equate technical severity with the organisation's overall risk decision.
- EPSS: per FIRST's definition it estimates the probability that a published CVE will be exploited in the wild in the next 30 days. It is not a score for the likelihood of an attack on your organisation, for breach impact, or for your own BOLA finding that has no CVE yet. Percentile is a ranking, not the same number as a probability.
- CWE/CAPEC: root cause and attack pattern; for the category in reports.
In these reports, rather than choosing a single metric, place CVSS + EPSS + impact side by side; the decision is not tied to one number.
ASCII: Asset -> Threat -> Control Mapping
asset: billing-api (prod, public)
threat: fake POST to the payment webhook
control: webhook signature verification (HMAC-SHA256)
control: webhook IP allowlist
control: replay protection (nonce + timestamp)
detection: signature mismatch -> log + alert
test: fake-signature test before every releaseWrite a similar block for each asset; when the blocks come together you get the product's risk map. Link the blocks to the risk register table in Section 6 above.
Mitigation Examples
| Risk | Mitigation | Detection |
|---|---|---|
| SQL injection | parameterized query, ORM, input validation | WAF anomaly, db error rate spike |
| SSRF | egress allowlist, metadata endpoint disabled | outbound connection to 169.254.169.254 |
| IDOR | owner check, random ID | 403/404 rate abnormally low, access pattern anomaly |
| XSS | CSP, output encoding, framework escape | CSP violation report |
| RCE via deserialization | safe serializer, type validation | unexpected process spawn |
| Privilege escalation | least privilege, sudoers review | sudo log anomaly |
For each mitigation, do not close the row without filling in the Detection column. Detection without mitigation is noise; mitigation without detection is a blind spot.
A Short Conclusion
Maturity in cyber security grows not from running more tools but from asking the right questions regularly. First make your assets visible, then rank risks by business impact, then manage the remediation process through ownership and evidence. A risk model is not a one-off; it is a living document updated before every release.
Example: A Mini Threat Model for One Feature
Say you added a new "password reset" flow. Assets: the user table, the mail service, the rate limit counter. Flows: user -> endpoint -> mail. Threats:
| Threat | Precondition | Impact | Control |
|---|---|---|---|
| Username enumeration | no rate limit | identity discovery | identical message, identical timing |
| Token guess | low entropy | account takeover | 128-bit random, single use |
| Token leak | long-lived | account takeover | 15-min validity, HTTPS |
| Mail bombing | no rate limit | DoS, reputation | per-IP + per-account limit |
This table turns into a risk register row; its owner and target are written down. A one-page threat model gets used more often than a document that runs page after page.
Risk Scoring: CVSS + EPSS + Impact
When deciding, the three numbers are read together:
- CVSS: the technical weight of the vulnerability.
- EPSS: the probability of exploitation.
- Business impact: what is lost in this system (data, revenue, reputation).
Do not collapse the three into one table and draw a colour chart; colour interpretation is subjective. Instead, use three separate columns and write a single decision sentence for each row. "This finding is closed within 7 days because it grants access to X data on the affected system."
Detection Inequalities
-When monitoring a service, three metrics stand together: QPS, error rate, and p95 latency. The definition of normal behaviour is the baseline of these three columns. Exception: an attack is not the single point where all three cross their thresholds. Sometimes the error rate rises on its own (a rate limit may have triggered), sometimes latency alone (resource exhaustion). Bind the alert to the combination rather than a single metric: +When monitoring a service, track QPS, error rate, and p95 latency against a representative baseline. Do not require all three to cross a threshold: a rate limit can raise errors alone, while resource exhaustion can raise latency first. The rules below are synthetic examples to show how signals can be combined, not production thresholds; calibrate them against normal traffic, release cycles, and tested alert consequences:
if error_rate > 5% and qps > baseline * 3: page
if latency_p95 > 3x baseline and cpu > 85%: investigate
if error_rate > 20% regardless: pageTo measure alert fatigue, produce a weekly "trigger count / accuracy" pair for each rule.
Mitigation Patterns: Quick Reference
| Category | Quick mitigation | Why the mitigation works |
|---|---|---|
| Authentication | MFA + short-lived session | A single already-stolen secret is not enough |
| Authorisation | central policy engine | You fix it from one place |
| Input validation | schema + allowlist | Dynamically cleaning strings is not enough |
| Output encoding | framework escape | The source of XSS is neglected encoding |
| Network | egress allowlist, mTLS | Prevents reaching into the internal network |
| Secret management | KMS, rotation, audit | A hard-coded secret is never kept safe by any code |
| Logging | structure + redaction | Raw logs become a data leak |
| Error handling | generic message, single id | A stack trace discloses information |
Going Deeper on Trust Boundaries
Two questions in front of every boundary:
- Which identity does the traffic crossing this boundary carry?
- Which rate limit, which timeout, which retry policy applies to this traffic?
Giving an anonymous client a token does not by itself provide identity; if the same person can obtain unlimited tokens, the per-token limit is defeated. Bound token issuance by resource, session, and operation cost as well. Use the IP header only on the ingress rewritten by a trusted proxy. Mass false positives caused by NAT do not justify treating an unverified token as a trusted actor.
Security Debt: Keeping It Visible
Like technical debt, security debt accumulates: a legacy endpoint, a temporary policy, a forgotten env variable. To manage it:
- Every debt item should have an owner and a termination date.
- The PR that adds the debt should contain a
// SECURITY-DEBTcomment. - The debt list should be reviewed every quarter; closed items are celebrated, open ones re-prioritised.
Debt does not defer when it is visible; when it is invisible it waits and grows.
Mitigation Verifier
Put a verification step next to every mitigation:
mitigation: tenant + membership + operation authorisation on the invoice query
fixture: tenant A and B; an artificial invoice in each
verify: a member of A can read their own invoice
verify: a member of A cannot retrieve data with B's invoice using a known id
verify: a viewer cannot write; finance can change the permitted field
evidence: version + masked request/response + DB side-effect checkA 400 or 500 code changing does not prove the control was fixed; the error may have been masked while the data effect persisted. A positive control should show the function works, and a negative control should show the trust boundary closed. If the result is uncertain, record the missing evidence and the re-review condition instead of claiming "risk reduced".
Related Research & Internal References
- API Access Control Test Plan - Turning the access-control part of the model into concrete tests.
- Shadow API Asset Inventory - Building the asset inventory from observed surface.
- Security Logging Design - The logging layer the detection columns depend on.
- Denied-Request Alert Triage - Turning the deny stream into signal instead of noise.
- Security Finding Scoring - Consistency when the same finding is scored by different people.
- CVE-2024-6387 Anatomy - Why a technical severity score is not the same as your risk.
What do you think?
React to show your appreciation