Skip to main content

Security Requirements & Threat Modeling Policy

Document control

FieldValue
OwnerRon Benisty — CTO & CSO (ron.b@iontwrks.com)
StatusApproved
Version1.0
ClassificationConfidential
Approved byRon Benisty — CTO & CSO
Approval date2026-05-26 (Tuesday)
Last reviewed2026-05-26
Review cycleAnnual — next review due May 2027
Parent policySecure SDLC (SSDLC)

Satisfies ISO/IEC 27001:2022 A.8.26 (application security requirements) and reinforces A.8.27 (secure architecture & engineering principles). Satisfies NIST SSDF PW.1 (design software to meet security requirements) and PW.2 (review the design to verify compliance). Closes Gap 6 of the SSDLC gap analysis.


1. Purpose

Two related disciplines, combined into one practice:

  • Security Requirements — for every meaningful chunk of new work, write down what security properties must hold before code starts. Data classification, authn/authz needs, audit logging, encryption, tenant isolation.
  • Threat Modeling — for the same chunk of work, run a structured "what could go wrong?" analysis at the design phase, using STRIDE against a data-flow diagram. The output refines and supplements the requirements.

The two halves go together because the requirements are the answers to threat modeling.

2. Scope — what triggers a threat model

Triggers a threat modelDoes not trigger
A new epic — a substantial chunk of new functionality (a new portal section, a new AI workflow, a new external integration, a new background-worker family, a new public API endpoint family)A normal feature PR inside an existing epic with no new trust boundary
Material design change to an existing epic — a new trust boundary, a new data flow, a new sub-processorBug fix
Adoption of a new sub-processor that handles tenant dataRefactor with no behavioral change
A new tenant-isolation pattern or a change to the existing oneA documentation change

When in doubt, ask: does this introduce a new trust boundary, a new data flow, or a new piece of sensitive data? If yes, threat-model.

3. Data classification

Every security-requirements document must classify the data it touches according to these four tiers:

TierExamplesHandling
PublicMarketing copy, open-source framework PDFs imported as reference, public CVE feedsNo special handling; safe in any environment
InternalS.E.T's own source code, runbooks, architecture docs, SBOMs, scan reportsRepo + internal systems; not for public sharing
ConfidentialTenant data, evidence files, security findings, audit logs, generated policies, BCP plans, vendor responsesProduction-only; tenant-scoped; encryption at rest + in transit; access logged
RestrictedCredentials, API keys, JWT signing keys, KMS keys, PII (names, emails, phone numbers, identity numbers), MFA seedsProduction-only; AWS Secrets Manager / KMS; never logged; never copied to non-prod; access alerted on

Higher tiers inherit the rules of lower tiers.

4. When threat modeling runs

The threat model must exist and be CTO & CSO-approved before the first PR of the epic merges to develop. Prototype / spike PRs are permitted to land on a feature branch without one, but cannot reach develop or main without the approved threat model.

Idea → Design draft → Threat model + Security requirements (this policy)
→ CTO & CSO approval → Implementation PRs (per Change Management)
→ Nonprod → Production

A threat model is re-reviewed on material design change: a new trust boundary, a new external system, a new tenant-data shape, or a new sub-processor.

5. Process — six steps

  1. Open the threat-model file at docs/threat-models/{epic-name}.md from the template.
  2. Draw the data-flow diagram as Mermaid. Identify every process, data store, data flow, external entity, and the trust boundaries between them.
  3. Apply STRIDE per element using the rules in §6 — for each element type, identify which STRIDE categories apply and what specific threats exist.
  4. Document the mitigation for each threat — either an existing control (link to the relevant policy / architecture section) or a new control (which becomes a security requirement on the epic).
  5. Fill the security-requirements section of the same document, classifying data per §3 and listing concrete requirements derived from the STRIDE analysis.
  6. CTO & CSO approves by PR review on the threat-model file. Once approved, the first implementation PR may merge.

6. STRIDE per element

The standard mapping — which threat categories apply to which element type. Apply each one:

Element typeSpoofingTamperingRepudiationInformation disclosureDenial of serviceElevation of privilege
Process (a service / function / worker)
Data flow (a message / API call / queue message)
Data store (a DB / S3 bucket / cache / queue)
External entity (a user / a sub-processor)

For each against an element, ask: can an attacker achieve this against this element? If yes, document the threat + mitigation in §4 of the threat-model file.

7. Threat-model template

Save as docs/threat-models/{epic-name}.md:

# Threat Model — {Epic Name}

**Author**: {name}
**Date**: {YYYY-MM-DD}
**Status**: Draft / Approved
**Approved by (CTO & CSO)**: {name + date once approved}
**Linked epic / issue**: #{issue}

## 1. System overview

One paragraph describing what this epic does and why.

## 2. Data-flow diagram

```mermaid
flowchart LR
User[External: MSSP Admin] -->|HTTPS + JWT| BFF[Process: NestJS BFF]
BFF -->|tenant search_path| DB[(Data store: tenant_xxx schema)]
BFF -->|S3 PUT| Evidence[(Data store: S3 Evidence bucket)]
subgraph TrustBoundary["Trust boundary: AWS VPC"]
BFF
DB
Evidence
end
```

## 3. Trust boundaries

- **External → Cloudflare**: TLS 1.2+; WAF; rate limit
- **Cloudflare → ALB**: mTLS Authenticated Origin Pulls; IP allowlist
- **BFF → tenant schema**: Tenant Context Middleware enforces `search_path`
- **BFF → S3**: IAM role + KMS encryption at rest

## 4. STRIDE analysis

| Element | Threat | Category | Mitigation |
|---|---|---|---|
| BFF | Spoofed JWT bypasses auth | S | WorkOS JWKS verification per Authentication policy |
| BFF → tenant schema | Cross-tenant query if `search_path` not set | T | Tenant Context Middleware + connection-pool `RESET search_path` |
| Evidence bucket | Unauthorized read of another tenant's evidence | I | Per-tenant S3 prefix + IAM policy + KMS CMK; CloudTrail logged |
| BFF | Unbounded query → DoS | D | Cloudflare rate limit + GraphQL complexity ≤ 1 000 |
| External user | Repudiates an action | R | Every mutation logged in tenant `audit_events` (append-only) |
| BFF | User elevates to admin without proper role | E | Per-route RBAC guard; CODEOWNERS-protected role-assignment code |

(Add one row per element/threat pair that has a `✓` in the STRIDE-per-element table.)

## 5. Security requirements derived from §4

1. All requests authenticated via WorkOS JWT — verified server-side via JWKS.
2. All DB queries set `search_path` via Tenant Context Middleware before any query runs.
3. All evidence uploads use a per-tenant S3 prefix + KMS encryption.
4. Every mutation emits an `audit_events` row with actor + tenant + action.
5. GraphQL queries on this epic are subject to depth ≤ 10 + complexity ≤ 1 000.
6. Data classification: **Confidential** (tenant evidence) + **Restricted** (any PII inside evidence).

## 6. Residual risks accepted

Any threat for which mitigation is deferred or accepted — list with the reason.

## 7. Review history

| Date | Reviewer | Outcome |
|---|---|---|
| {YYYY-MM-DD} | CTO & CSO | Approved / Changes requested |

8. Security-requirements-only template (smaller changes)

For changes that touch sensitive data but don't introduce a new trust boundary (e.g. a new field on an existing endpoint), use a slimmed-down requirements document — only §1, §5, §6 of the full template above. CTO & CSO approval still required.

9. Complementary view — MITRE ATT&CK at runtime

STRIDE answers "is the design exploitable?" — applied at design time, per epic, in this policy.

MITRE ATT&CK answers "what are real attackers doing at runtime?" — a catalog of adversary tactics, techniques, and procedures (TTPs) observed in the wild. ATT&CK has its proper home in operations, not design:

  • Observability §Security alerting — Logz.io detection rules tag findings with the matching ATT&CK technique ID(s) (e.g. T1078 valid-account abuse, T1190 exploitation of public-facing application).
  • Incident Response §9 — incident records classify observed activity by ATT&CK tactic + technique.

Threat modelers may optionally annotate STRIDE rows in §4 with the ATT&CK technique an attacker would use to realize that threat — useful for downstream detection-rule writers, not required.

10. Evidence + retention

  • Each threat model is one Markdown file in docs/threat-models/, version-controlled with the codebase.
  • Approval is recorded as the CTO & CSO PR review on that file.
  • Retained for the lifetime of the epic + 24 months thereafter, per the Evidence Collection & Retention Policy.

11. Document change history

VersionDateAuthorDescription of changeApproved by
1.02026-05-26Ron Benisty (CTO & CSO)Initial version — STRIDE-based per-epic threat modeling + four-tier data classification + Markdown+Mermaid templates + design-complete approval gate + cross-reference to MITRE ATT&CK at runtime.Ron Benisty (CTO & CSO)