☁️ tfSTRIDE: Building a Multi-Cloud Terraform Threat Modeling Engine

June 22, 2026

A provider-plugin threat modeling engine that turns multi-cloud Terraform plans into normalized infrastructure facts, trust boundaries, STRIDE findings, and CI-ready policy gates.

The Problem

Terraform plans are readable, but they are still easy to misjudge when IAM trust, network posture, and private data access interact - especially as plans grow beyond a handful of obvious resources.

A plan can look reasonable at first glance while still hiding quiet transitive exposure paths. An internet-facing load balancer may lead to a private workload. A workload role may carry broader permissions than expected. A database or secret may not be directly public, but still be reachable through a chain of trusted components.

That is the problem I wanted to solve. Rather than relying on manual review of raw plan JSON, I wanted a transparent way to identify those crossings before deployment: trust boundaries, sensitive access paths, and findings that are explainable enough for both human review and CI gating.

Why I Built It

Most Terraform review workflows still depend on a mix of manual inspection, generic misconfiguration checks, and policy tooling that can tell you a rule was violated without making the underlying trust path obvious.

That works for simple cases, but it breaks down quickly once network exposure, IAM trust, workload identity, and private data access start interacting. A plan may not contain an obviously public database or a blatantly open secret, but it can still create a risky path through a chain of trusted components.

I built tfSTRIDE to make those paths easier to review before deployment. The goal was not to build a full cloud security platform or a black-box scanner. It was to build a stable, explainable pre-deploy review engine that could turn Terraform plan JSON into normalized infrastructure facts, trust boundaries, evidence-backed findings, and CI-friendly output.

A few design constraints shaped the project from the start:

  • predictable analysis, with no LLM in the core path
  • explainable findings backed by concrete evidence
  • AWS-first support with a deliberately curated resource set
  • the same engine powering both the CLI and the dashboard

That scoping was intentional - I wanted something focused enough to stay understandable, stable, and useful in real review workflows.

What the Tool Does

tfSTRIDE takes Terraform plan JSON and turns it into a pre-deploy security review for AWS infrastructure.

Given the output of terraform show -json, it normalizes supported resources, identifies trust boundaries, evaluates STRIDE-oriented rules, and produces evidence-backed findings plus observed protective controls.

The same analysis path can be used in three ways:

  • CLI review for local analysis
  • Dashboard upload for interactive inspection
  • CI policy gating with markdown, JSON and SARIF output

The goal is to make risky infrastructure paths easier to see before terraform apply, especially when IAM trust, network exposure, and private data access interact.

The live demo is available at tfstride.beane.me and the project is open source on GitHub.

Core Design Choices

A few decisions shaped the project from the start:

  1. Deterministic analysis

    The core path is fully reproducible: no LLMs, no runtime cloud access, and no hidden enrichment steps. The same plan should produce the same result every time, which matters for both trust and CI use.

  2. Normalized infrastructure model

    Rules operate on normalized infrastructure facts rather than raw Terraform JSON. That keeps the analysis layer smaller, more composable, and easier to explain.

  3. Trust boundaries first

    Instead of focusing only on isolated misconfigurations, the engine identifies crossings that matter: internet exposure, workload-to-data access, cross-account trust, and control-plane relationships. That makes quieter transitive risk easier to surface.

  4. One engine, multiple interfaces

    The CLI, JSON report, SARIF output, and dashboard all sit on top of the same core engine. The dashboard is intentionally thin so the logic stays in one place.

  5. Honest, curated scope

    The project is AWS-first and intentionally limited in coverage. The goal is not universal policy enforcement; it is explainable, pre-deploy review over a focused and validated surface area.

Architecture Diagram

tfSTRIDE pre-deploy threat modeling architectureTerraform plan JSON enters through the CLI or dashboard. tfSTRIDE loads the plan, selects an AWS, GCP, or AzureRM provider plugin, normalizes and decorates resources, builds shared analysis indexes, detects trust boundaries, evaluates STRIDE rules, applies policy filters, and renders Markdown, JSON, SARIF, dashboard, and CI outputs.tfSTRIDE pre-deploy threat modeling architectureDeterministic Terraform plan analysis through provider-owned normalization and a shared, explainable security engine.offline analysisno LLMINPUTSAPPLICATIONPROVIDER PLUGINSSHARED ANALYSISTerraform plan JSONterraform show -jsonplanned values onlyProject configurationtfstride.tomlprovider + rule policyFinding filterssuppressionsaccepted baselineEntrypointsCLIdashboard / APITerraform plan loaderparse resource recordspreserve source pathProvider registryauto-detect or explicitreject mixed providersAnalysis orchestrationanalyze_plan()assemble AnalysisResultProviderPlugin contractselected from normalized provider ownershipAWSEC2, ECS, Lambda, EKS, RDS, S3IAM, VPC, trust boundariesGCPCompute, GKE, Cloud SQL, GCSfirewall, IAM, serverless dataAzureRMStorage, Key Vault, SQL, AKSidentity, RBAC, LB exposureCONTRIBUTION SEAMSnormalizer · decorator · facts · capabilitiesrules · metadata · boundaries · optional indexesNormalized inventoryprovider-neutral resourcesrelationships + unsupported coverageAnalysis indexesroles + security groupsoptional provider extensionTrust-boundary engineshared contributorsselected provider contributorSTRIDE rule engineprovider rule contributionsevidence + severity reasoningResult assemblyfindings + observationscoverage + limitationsPolicy filteringseverity overridessuppress + baselineREVIEW & AUTOMATION OUTPUTSMarkdownhuman review reportJSON contractversioned automationSARIFscanner integrationDashboardCI gate--fail-on severitydeterministic fixtures and golden reports characterize the complete pipeline
Provider packages own cloud-specific normalization and security knowledge. Shared orchestration remains provider-neutral and powers the CLI, dashboard, reports, and CI policy gate.

Example Findings

  1. Transitive private-data exposure
    #### Sensitive data tier is transitively reachable from an internet-exposed path
    
    - STRIDE category: Information Disclosure
    - Affected resources: `aws_lb.web`, `aws_ecs_service.app`, `aws_db_instance.app`
    - Rationale: `aws_db_instance.app` is not directly public, but internet traffic can first reach `aws_lb.web`, move through the ECS service path, and then cross into the private data tier.
    - Evidence:
      - network path: internet reaches `aws_lb.web`; `aws_lb.web` reaches `aws_ecs_service.app`; `aws_ecs_service.app` reaches `aws_db_instance.app`
      - data tier posture: `aws_db_instance.app` is not directly public; database has no direct internet ingress path
  2. Workload role carries sensitive permissions
    #### Workload role carries sensitive permissions
    
    - STRIDE category: Elevation of Privilege
    - Affected resources: `aws_lambda_function.processor`, `aws_iam_role.app`
    - Rationale: `aws_lambda_function.processor` inherits sensitive privileges from `aws_iam_role.app`, including `kms:Decrypt` and `sts:AssumeRole`. If the workload is compromised, those credentials can be reused for escalation or broader data access.
    - Evidence:
      - iam actions: `kms:Decrypt`; `sts:AssumeRole`
      - policy statements: `Allow actions=[*, kms:Decrypt, sts:AssumeRole] resources=[*]`

Extension to ECS/Fargate

A useful architecture test for the project was extending support into ECS / Fargate.

Initially, ECS resources were unsupported, which meant the engine could still reason about surrounding infrastructure but could not yet treat an ECS service as a workload with network posture, IAM context, and downstream data access. The missing piece was normalization.

To fix that, I added ECS service and task definition normalization that resolves task roles, execution roles, subnets, security groups, and load balancer context into the same internal model used by other workload types.

That change mattered because it let existing trust-boundary and rule logic extend cleanly into ECS-backed systems. Once normalized, the engine could detect workload-to-data-store access, sensitive task-role permissions, and transitive private-data exposure from internet-facing entry points into Fargate-backed services.

The result was less about "adding ECS support" and more about proving the model could survive a new compute primitive without becoming a collection of one-off rules.

CI & Policy Gating

The project was built to work in CI, not just as a local analysis tool.

Alongside markdown output for human review, the engine produces a versioned JSON report for automation and SARIF for scanner-compatible integrations. It also supports fail-on severity thresholds so a Terraform plan can be gated before deployment.

To keep that workflow practical, I added baselines and suppressions. That allows CI to focus on newly introduced findings while keeping accepted exceptions explicit and reviewable.

The same analysis path now supports local CLI review, dashboard-based inspection, and pre-deploy policy gating in CI.

terraform plan -out tfplan
terraform show -json tfplan > tfplan.json
tfstride tfplan.json --quiet --fail-on high --sarif-output tfstride-output.sarif

Tradeoffs & Limitations

tfSTRIDE is intentionally scoped - the goal is not to model the entire Terraform AWS provider or replace runtime cloud security tooling. The goal is to provide explainable pre-deploy review over a focused set of infrastructure patterns that are easy to misjudge by eye.

That tradeoff shaped the project in a few ways:

  • AWS-first, curated support

    The engine supports a deliberately limited AWS resource set rather than claiming universal Terraform coverage. That keeps the normalization layer and rule behavior understandable, testable, and easier to trust.

  • Plan-based analysis only

    The engine reasons over Terraform planned values. It does not validate runtime drift, CloudTrail activity, or post-deploy control-plane behavior, and it does not make cloud API calls during analysis.

  • Focused trust and policy modeling

    IAM trust analysis, resource-policy analysis, and condition handling are intentionally selective. The engine models common and meaningful paths such as ExternalId, SourceArn, and SourceAccount, but it does not attempt to cover every AWS service-specific authorization edge case.

  • Explainability over total coverage

    The project prefers a smaller number of evidence-backed findings over broad, opaque coverage. That means some edge cases remain intentionally out of scope if supporting them would make the output harder to reason about.

  • Not a full graph platform

    The engine identifies trust boundaries and composes specific transitive paths that matter for review, but it is not trying to be a general-purpose cloud graph engine or a full attack-path platform.

Those constraints are deliberate. I wanted the output to stay predictable, stable, and understandable enough for both human review and CI gating, even if that meant keeping the first version narrower in scope.

What I'd Improve Next

The current version is intentionally focused, but there are a few areas where I'd extend it next.

The first is broader workload modeling. ECS/Fargate support was a useful proof point for the normalization model, and I'd like to extend the same trust-boundary approach into additional AWS compute patterns and service combinations to test whether the abstractions continue to hold as architectures become more complex.

The second is tighter rule precision around common AWS patterns. Some cases, especially around broadly scoped execution-role permissions and service-specific policy behavior, can be mechanically correct while still benefiting from more AWS-aware exceptions and better prioritization.

I'd also like to improve how the engine explains composed paths. The current findings already surface transitive exposure, but there is room to make those paths easier to inspect visually and easier to understand at a glance in both the dashboard and report output.

Longer term, I'd expand the supported resource set carefully rather than broadly, keeping the same design goal in place: reproducible, explainable analysis over a validated surface area instead of shallow coverage across everything.

Security review should not depend on who happens to read the plan. It should be repeatable, explainable, and early enough to matter.