✳ Field lesson A1 / 9 min

Threat modeling a service: data flows, trust boundaries, and STRIDE

Threat modeling is a structured engineering review that decomposes an application into processes, data stores, data flows, and trust boundaries, then systematically evaluates where Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, or Elevation of Privilege (STRIDE) can occur.

appsecthreat-modelingtrust-boundaryshopcartCISSP D1CISSP D8CCSP D4

Helpful first: Threat, vulnerability, and risk: the core equation · Least privilege, defense in depth, and Zero Trust boundaries · Application trust boundaries: why the client UI is never a security gate

Key points

  • Draw a Data Flow Diagram (DFD) with explicit trust boundaries before evaluating code-level vulnerabilities
  • Apply the STRIDE taxonomy to identify design-level threats at each boundary crossing
  • Write concrete mitigation requirements and verification tests directly into the engineering specification

Four questions that anchor every threat model

Fixing an architectural flaw during design review costs an hour at a whiteboard; fixing the same flaw after production deployment costs an emergency migration, rotated keys, and customer incident notifications. At Meridian Space & Robotics (chronos.orbital), Principal Security Architect Vera Vance runs every new service through Shostack’s four threat-modeling questions: (1) What are we building? (2) What can go wrong? (3) What are we going to do about it? (4) Did we do a good job?

To answer Question 1 ("What are we building?"), Propulsion Lead Priya Nair and Vera sketch a Data Flow Diagram (DFD) for Meridian’s Payload Booking Portal (portal.chronos.orbital). Every DFD uses four building blocks: External Entities (users, third-party APIs), Processes (microservices, workers), Data Stores (databases, queues, S3 buckets), and Data Flows (HTTPS requests, gRPC streams), intersected by dashed Trust Boundaries wherever privilege or execution context changes.

A Data Flow Diagram (DFD) for the Payload Booking Portal (portal.chronos.orbital) uses External Entities, Processes, Data Stores, and Data Flows. Dashed Trust Boundaries mark each place privilege changes.
The STRIDE threat taxonomy mapped to security properties and Meridian controls
STRIDE CategoryProperty ViolatedDesign Question at the BoundaryPrimary Engineering Control
SpoofingAuthenticationCan a caller forge its human or workload identity across this arrow?FIDO2/OIDC for humans; SPIFFE/mTLS workload certificates for service-to-service calls
TamperingIntegrityCan an attacker modify parameters, prices, or burn vectors in transit or in storage?Server-side state recalculation, HMAC/digital signatures, parameterized SQL queries
RepudiationNon-repudiation / AccountabilityCan an actor deny approving a launch payload or deleting a record?Cryptographically signed audit events written to an append-only log sink
Information DisclosureConfidentialityCan unauthorized tenants read another customer’s orbital manifest or error stack traces?Row-level tenant scoping, TLS 1.3, KMS envelope encryption, sanitized error responses
Denial of ServiceAvailabilityCan an unauthenticated caller exhaust CPU, memory, connection pools, or disk?Per-tenant token-bucket rate limiting, bounded payload sizes, circuit breakers
Elevation of PrivilegeAuthorizationCan a standard customer invoke an internal flight-director endpoint?Deny-by-default server-side RBAC/ABAC checks on every route and object ID
At one Trust Boundary, each STRIDE question maps to one property and one control: Spoofing to Authentication, Tampering to Integrity, Repudiation to Non-repudiation / Accountability, Information Disclosure to Confidentiality, Denial of Service to Availability, and Elevation of Privilege to Authorization.

Walking the trust boundaries on a checkout and booking flow

Suppose a satellite customer submits a payload reservation from their browser to portal.chronos.orbital. The first trust boundary sits between the untrusted browser and the API gateway. If the client sends { "payloadKg": 500, "quotedPriceUsd": 100 } in the POST body and the backend trusts quotedPriceUsd instead of looking up the rate card in the database, that is a classic Tampering flaw.

A second trust boundary sits between the Booking API service and the Payment/Invoicing worker. Even though both run inside Meridian’s cloud account, a compromised frontend pod should never have raw SQL credentials to the invoicing ledger. Placing an explicit trust boundary between the web tier and the ledger forces the team to authenticate the service caller and validate the schema of every internal message.

Boundary 1 is Tampering: the backend trusts quotedPriceUsd instead of the rate card in the database. Boundary 2 holds: a compromised frontend pod has no raw SQL credentials to the invoicing ledger. The worker authenticates the service caller and validates the schema.

Turning threats into testable engineering controls

A threat model that ends as a forgotten wiki diagram is security theater. For every high-priority STRIDE finding, Vera and Priya write a falsifiable acceptance test right into the pull-request checklist.

For example, to close the price-tampering threat, the engineering requirement states: "The POST /v1/bookings handler accepts only customerId, orbitClass, and payloadKg; price is computed server-side from the signed rate table." The accompanying integration test sends a mutated quotedPriceUsd: 1 field and asserts that the server ignores or rejects it with HTTP 400.

The price-tampering threat becomes a requirement on POST /v1/bookings: accept customerId, orbitClass, and payloadKg, and price from the signed rate table. The test sends quotedPriceUsd: 1 and expects HTTP 400.

CHECK YOUR JUDGMENT

During a design review of Meridian’s Payload Booking Portal (portal.chronos.orbital), Propulsion Lead Priya Nair notices that when a customer downloads a mission invoice via GET /v1/invoices?invoiceId=8841, the backend verifies the customer’s OIDC session token but queries the database using only WHERE invoice_id = $1 without checking which customer organization owns invoice 8841. Under STRIDE, which two categories best describe this design flaw, and what is the fix?

NEXT FIELD LESSON

Direct and transitive dependencies: inherited code in your runtime

↗

Find your next idea.

Tip: press / to open search. Escape closes this window.