agentsclimarketplace

Threat modeling

Skill vindreshsingh/engineering-skills/skills/threat-modeling

Finds security risks at design time — before code exists — by mapping the system, enumerating how it could be attacked, and deciding what to do about each threat. Use when designing a feature that touches auth, data, money, or external input, when changing a trust boundary, or when a security-sensitive change needs a structured risk pass rather than a code-level review.From its SKILL.md

Install
npx -y skills add vindreshsingh/engineering-skills --skill threat-modeling

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.2 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it

Threat Modeling

Most security work happens too late — at code review ([[hardening]]) or in production ([[incident-response]]), after the expensive decisions are already baked in. Threat modeling moves the security thinking to design time: look at what you're about to build, ask how would someone attack this?, and decide — mitigate, accept, or redesign — before a line is written. It answers four questions: what are we building, what can go wrong, what are we going to do about it, and did we do a good job?

This is design-phase security, distinct from [[hardening]] (finding issues in a written diff) and [[agent-guardrails]] (runtime blocking of dangerous actions). It feeds those: the model says where to harden and what the guardrails must protect.

When to Use

  • Designing a feature touching authentication, authorization, payments, PII, or secrets
  • Adding or changing a trust boundary — a new external input, integration, upload, or service call
  • A [[spec-first]] / [[interface-design]] pass on anything security-sensitive, before implementation
  • Before a risky [[migration-path]] that moves or exposes data differently
  • A security-sensitive change needs a structured risk pass, not just a code skim

Skip when the change has no security-relevant surface (internal refactor, copy change, styling) — don't ceremony-model a CSS tweak. For an already-written diff, use [[hardening]]; for a live attack or breach, use [[incident-response]].

Not a substitute for [[hardening]] (code-level verification) — threat modeling decides what matters; hardening confirms the code got it right.

Process

1. Model what you're building — draw the data flow

Sketch the system: components, data stores, external entities, and the trust boundaries they cross (user→app, app→DB, app→third-party, internet→service). You can't reason about attacks you can't see; a simple data-flow diagram beats prose. Mark where data is most sensitive and where input is least trusted.

2. Enumerate threats — be systematic, not lucky

Walk each element and boundary with a checklist so you don't just list the threats you happened to think of. STRIDE is the common lens:

CategoryThe threatAsk
SpoofingPretending to be someone elseCan identity be faked? Is auth enforced here?
TamperingUnauthorized modificationCan data/requests be altered in transit or at rest?
RepudiationDenying an actionIs there an audit trail for sensitive actions?
Info disclosureLeaking dataCan someone read data they shouldn't? Over-broad responses, logs, errors?
Denial of serviceMaking it unavailableCan input exhaust resources? Rate limits?
Elevation of privilegeGaining more accessCan a normal user reach admin actions? IDOR?

Pay special attention to untrusted input (every external field, file, header, webhook) and authorization at each boundary (authentication ≠ authorization — check both).

3. Rate each threat by risk

Score roughly by likelihood × impact. A trivially-exploitable PII leak outranks a theoretical DoS needing insider access. You're prioritizing, not writing a thesis — high / medium / low is enough to sequence the response.

4. Decide a response for every threat — the four options

For each threat, pick one and write it down:

  • Mitigate — add a control (authz check, validation, rate limit, encryption, signed token)
  • Eliminate — redesign so the threat can't exist (don't store the secret; don't accept the input)
  • Transfer — push it to a system built for it (managed auth, a payment processor, a WAF)
  • Accept — consciously, with a recorded reason and an owner (only for low risk)

"Mitigate" turns into concrete work items for the build; "accept" is a decision, not an oversight — record it ([[decision-docs]]).

5. Don't forget abuse, not just bugs

Model misuse: a logged-in user attacking other users' data (IDOR), automation abusing a free tier, a malicious file upload, prompt injection into an LLM feature ([[llm-feature-engineering]]). Many real breaches are authorized users doing unauthorized things, not classic exploits.

6. Feed the result into build and verification

Each mitigation becomes a task and an acceptance criterion. Hand the list to [[hardening]] as the review checklist for the diff, and to [[test-first]] so high-risk threats get a test that proves the control works. Note runtime invariants for [[agent-guardrails]] / [[observability]] (alerting on the attack signature).

7. Validate the model — did we do a good job?

Re-check: every trust boundary enumerated, every untrusted input has a validation decision, every sensitive action has authz and an audit trail, and every threat has a recorded response. A model with "no threats found" on an auth/payments feature is a model that wasn't done.

Common Rationalizations

  • "We'll catch it in code review." — Review finds bugs in what you built; threat modeling changes what you build. Some fixes are impossible to bolt on later.
  • "It's internal, no one will attack it." — Internal users, compromised creds, and SSRF make "internal" a weak boundary; model it.
  • "Authentication covers it." — Authentication is who you are; authorization is what you may do. IDOR lives in that gap.
  • "STRIDE is overkill here." — Then it's a five-minute pass; the checklist exists so you don't miss the category you didn't think of.
  • "No threats found." — On an auth/data/money surface that almost always means the model was too shallow, not that it's safe.
  • "We'll just accept the risk." — Acceptance is valid only when written down with a reason and an owner; silent acceptance is negligence.

Red Flags

  • No data-flow / trust-boundary picture — modeling from memory
  • Threats listed ad hoc instead of walked through a checklist (STRIDE or equivalent)
  • Untrusted input with no explicit validation decision
  • Authentication present but per-resource authorization unchecked (IDOR risk)
  • Sensitive actions with no audit trail
  • Threats enumerated but several left with no recorded response
  • "Accepted" risks with no reason, owner, or revisit date

Verification

  • System modeled with components, data stores, external entities, and trust boundaries
  • Threats enumerated systematically (STRIDE or equivalent), not ad hoc
  • Untrusted inputs and per-boundary authorization explicitly examined
  • Each threat rated by likelihood × impact and prioritized
  • Every threat has a recorded response (mitigate / eliminate / transfer / accept-with-owner)
  • Abuse/misuse cases (IDOR, upload, automation, prompt injection) considered, not just bugs
  • Mitigations handed to [[test-first]] (high-risk tests) and [[hardening]] (review checklist); accepted risks in [[decision-docs]]

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.