Built-in scenario

sample_aws_nightmare_plan.json

Nightmare Plan Demo

Analyzed sample_aws_nightmare_plan.json with 25 normalized resources and 19 trust boundaries.

Analyze another plan

Active findings

16

Trust boundaries

19

Resources

25

Observations

0
High 5
Medium 11
Low 0

Findings

Severity bands

High

5

Database is reachable from overly permissive sources

aws-database-permissive-ingress

aws_db_instance.customer is a sensitive data store, but database is not marked directly internet reachable, but its security groups allow internet-origin ingress, and database trusts security groups attached to internet-exposed workloads. That weakens the expected separation between the workload tier and the data tier.

Category
Information Disclosure
Boundary
workload-to-data-store:aws_instance.admin->aws_db_instance.customer
Resources
aws_db_instance.customer, aws_security_group.db
Evidence
  • security group rules: aws_security_group.db ingress tcp 5432 from 0.0.0.0/0 (Postgres from internet); aws_security_group.db ingress tcp 5432 from sg-bad-admin-001, sg-bad-front-001 (Postgres from public tiers)
  • network path: database is not marked directly internet reachable, but its security groups allow internet-origin ingress; database trusts security groups attached to internet-exposed workloads; aws_security_group.db allows sg-bad-front-001, sg-bad-admin-001 attached to aws_instance.admin, aws_instance.frontend, aws_lb.web
  • subnet posture: aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route; aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route; aws_lb.web sits in public subnet aws_subnet.public_web with an internet route

Private data tier directly trusts the public application tier

aws-missing-tier-segmentation

aws_db_instance.customer accepts traffic from security groups attached to internet-facing workloads. A compromise of the public tier can therefore move laterally into the private data tier.

Category
Tampering
Boundary
public-subnet-to-private-subnet:aws_subnet.public_web->aws_subnet.private_ops
Resources
aws_db_instance.customer, aws_instance.admin, aws_instance.frontend, aws_lb.web, aws_security_group.db
Evidence
  • security group rules: aws_security_group.db ingress tcp 5432 from sg-bad-admin-001, sg-bad-front-001 (Postgres from public tiers)
  • network path: aws_security_group.db allows sg-bad-front-001, sg-bad-admin-001 attached to aws_instance.admin, aws_instance.frontend, aws_lb.web
  • subnet posture: aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route; aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route; aws_lb.web sits in public subnet aws_subnet.public_web with an internet route

Role trust relationship expands blast radius

aws-role-trust-expansion

aws_iam_role.app can be assumed by *. Broad or foreign-account trust relationships increase the chance that compromise in one identity domain spills into another.

Category
Elevation of Privilege
Boundary
cross-account-or-role-access:*->aws_iam_role.app
Resources
aws_iam_role.app
Evidence
  • trust principals: *
  • trust path: trust policy allows any AWS principal

Workload role carries sensitive permissions

aws-workload-role-sensitive-permissions

aws_lambda_function.processor inherits sensitive privileges from aws_iam_role.app, including *, kms:Decrypt, sts:AssumeRole. If the workload is compromised, those credentials can be reused for privilege escalation, data access, or role chaining.

Category
Elevation of Privilege
Boundary
admin-to-workload-plane:aws_iam_role.app->aws_lambda_function.processor
Resources
aws_lambda_function.processor, aws_iam_role.app
Evidence
  • iam actions: *; kms:Decrypt; sts:AssumeRole
  • policy statements: Allow actions=[*, kms:Decrypt, sts:AssumeRole] resources=[*]

Workload role carries sensitive permissions

aws-workload-role-sensitive-permissions

aws_lambda_function.deployer inherits sensitive privileges from aws_iam_role.pipeline, including iam:PassRole, s3:*. If the workload is compromised, those credentials can be reused for privilege escalation, data access, or role chaining.

Category
Elevation of Privilege
Boundary
admin-to-workload-plane:aws_iam_role.pipeline->aws_lambda_function.deployer
Resources
aws_lambda_function.deployer, aws_iam_role.pipeline
Evidence
  • iam actions: iam:PassRole; s3:*
  • policy statements: Allow actions=[iam:*, iam:PassRole, s3:*] resources=[*]

Medium

11

Cross-account or broad role trust lacks narrowing conditions

aws-role-trust-missing-narrowing

aws_iam_role.app trusts * without supported narrowing conditions such as `sts:ExternalId`, `aws:SourceArn`, or `aws:SourceAccount`. That leaves the assume-role path dependent on a broad or external principal match alone.

Category
Elevation of Privilege
Boundary
cross-account-or-role-access:*->aws_iam_role.app
Resources
aws_iam_role.app
Evidence
  • trust principals: *
  • trust scope: principal is wildcard
  • trust narrowing: supported narrowing conditions present: false; supported narrowing condition keys: none

Cross-account or broad role trust lacks narrowing conditions

aws-role-trust-missing-narrowing

aws_iam_role.pipeline trusts arn:aws:iam::444455556666:root without supported narrowing conditions such as `sts:ExternalId`, `aws:SourceArn`, or `aws:SourceAccount`. That leaves the assume-role path dependent on a broad or external principal match alone.

Category
Elevation of Privilege
Boundary
cross-account-or-role-access:arn:aws:iam::444455556666:root->aws_iam_role.pipeline
Resources
aws_iam_role.pipeline
Evidence
  • trust principals: arn:aws:iam::444455556666:root
  • trust scope: principal is foreign account root 444455556666
  • trust narrowing: supported narrowing conditions present: false; supported narrowing condition keys: none

Database storage encryption is disabled

aws-rds-storage-encryption-disabled

aws_db_instance.customer stores sensitive data, but `storage_encrypted` is disabled. That weakens data-at-rest protections for underlying storage, snapshots, and backup handling.

Category
Information Disclosure
Boundary
not-applicable
Resources
aws_db_instance.customer
Evidence
  • encryption posture: storage_encrypted is false; engine is postgres

IAM policy grants wildcard privileges

aws-iam-wildcard-permissions

aws_iam_role.app contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
aws_iam_role.app
Evidence
  • iam actions: *
  • iam resources: *
  • policy statements: Allow actions=[*, kms:Decrypt, sts:AssumeRole] resources=[*]

IAM policy grants wildcard privileges

aws-iam-wildcard-permissions

aws_iam_role.pipeline contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
aws_iam_role.pipeline
Evidence
  • iam actions: iam:*; s3:*
  • iam resources: *
  • policy statements: Allow actions=[iam:*, iam:PassRole, s3:*] resources=[*]

IAM policy grants wildcard privileges

aws-iam-wildcard-permissions

aws_iam_policy.admin_like contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.

Category
Elevation of Privilege
Boundary
not-applicable
Resources
aws_iam_policy.admin_like
Evidence
  • iam actions: ec2:*; iam:*; s3:*
  • iam resources: *
  • policy statements: Allow actions=[ec2:*, s3:*, iam:*] resources=[*]

Internet-exposed compute service permits overly broad ingress

aws-public-compute-broad-ingress

aws_instance.frontend is reachable from the internet and at least one attached security group allows administrative access or all ports from 0.0.0.0/0. That broad ingress raises the chance of unauthenticated probing and credential attacks.

Category
Spoofing
Boundary
internet-to-service:internet->aws_instance.frontend
Resources
aws_instance.frontend, aws_security_group.frontend
Evidence
  • security group rules: aws_security_group.frontend ingress tcp 0-65535 from 0.0.0.0/0 (Everything from the internet)
  • public exposure reasons: instance has a public IP path and attached security groups allow internet ingress
  • subnet posture: aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route

Internet-exposed compute service permits overly broad ingress

aws-public-compute-broad-ingress

aws_instance.admin is reachable from the internet and at least one attached security group allows administrative access or all ports from 0.0.0.0/0. That broad ingress raises the chance of unauthenticated probing and credential attacks.

Category
Spoofing
Boundary
internet-to-service:internet->aws_instance.admin
Resources
aws_instance.admin, aws_security_group.admin
Evidence
  • security group rules: aws_security_group.admin ingress tcp 3389 from 0.0.0.0/0 (RDP from internet)
  • public exposure reasons: instance has a public IP path and attached security groups allow internet ingress
  • subnet posture: aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route

Object storage is publicly accessible

aws-s3-public-access

aws_s3_bucket.assets appears to be public through ACLs or bucket policy. Public object access is a common source of unintended data disclosure.

Category
Information Disclosure
Boundary
internet-to-service:internet->aws_s3_bucket.assets
Resources
aws_s3_bucket.assets
Evidence
  • public exposure reasons: bucket ACL `public-read` grants public access; bucket policy allows anonymous access

Object storage is publicly accessible

aws-s3-public-access

aws_s3_bucket.backups appears to be public through ACLs or bucket policy. Public object access is a common source of unintended data disclosure.

Category
Information Disclosure
Boundary
internet-to-service:internet->aws_s3_bucket.backups
Resources
aws_s3_bucket.backups
Evidence
  • public exposure reasons: bucket ACL `public-read-write` grants public access

Role trust relationship expands blast radius

aws-role-trust-expansion

aws_iam_role.pipeline can be assumed by arn:aws:iam::444455556666:root. Broad or foreign-account trust relationships increase the chance that compromise in one identity domain spills into another.

Category
Elevation of Privilege
Boundary
cross-account-or-role-access:arn:aws:iam::444455556666:root->aws_iam_role.pipeline
Resources
aws_iam_role.pipeline
Evidence
  • trust principals: arn:aws:iam::444455556666:root
  • trust path: trust principal belongs to foreign account 444455556666

Low

0

No low findings.

Observations

Controls and mitigating signals

No observations were recorded for this plan.

Trust boundaries

Crossings that drive the model

admin-to-workload-plane

aws_iam_role.app -> aws_lambda_function.processor

IAM configuration acts as a control-plane boundary because the workload inherits whatever privileges the role carries.

admin-to-workload-plane

aws_iam_role.pipeline -> aws_lambda_function.deployer

IAM configuration acts as a control-plane boundary because the workload inherits whatever privileges the role carries.

cross-account-or-role-access

* -> aws_iam_role.app

An additional role or principal can cross into this role's trust boundary.

cross-account-or-role-access

arn:aws:iam::444455556666:root -> aws_iam_role.pipeline

A foreign AWS account can cross into this role's trust boundary.

internet-to-service

internet -> aws_instance.admin

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> aws_instance.frontend

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> aws_lb.web

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> aws_s3_bucket.assets

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

internet-to-service

internet -> aws_s3_bucket.backups

The resource is directly reachable or intentionally exposed to unauthenticated network clients.

public-subnet-to-private-subnet

aws_subnet.public_web -> aws_subnet.private_data

The VPC contains both publicly routable and private network segments that should be treated as separate trust zones.

public-subnet-to-private-subnet

aws_subnet.public_web -> aws_subnet.private_ops

The VPC contains both publicly routable and private network segments that should be treated as separate trust zones.

workload-to-data-store

aws_instance.admin -> aws_db_instance.customer

Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

workload-to-data-store

aws_instance.frontend -> aws_db_instance.customer

Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

workload-to-data-store

aws_lambda_function.deployer -> aws_db_instance.customer

Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

workload-to-data-store

aws_lambda_function.deployer -> aws_s3_bucket.assets

Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:*.

workload-to-data-store

aws_lambda_function.deployer -> aws_s3_bucket.backups

Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:*.

workload-to-data-store

aws_lambda_function.processor -> aws_db_instance.customer

Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

workload-to-data-store

aws_lambda_function.processor -> aws_s3_bucket.assets

Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as *.

workload-to-data-store

aws_lambda_function.processor -> aws_s3_bucket.backups

Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as *.

Raw outputs

Stable contract and markdown

JSON report
{
  "kind": "cloud-threat-model-report",
  "version": "1.1",
  "tool": {
    "name": "cloud-threat-modeler",
    "version": "0.1.0"
  },
  "title": "Nightmare Plan Demo",
  "analyzed_file": "sample_aws_nightmare_plan.json",
  "analyzed_path": "/home/fleet/cloud-threat-modeler/fixtures/sample_aws_nightmare_plan.json",
  "summary": {
    "normalized_resources": 25,
    "unsupported_resources": 0,
    "trust_boundaries": 19,
    "active_findings": 16,
    "total_findings": 16,
    "suppressed_findings": 0,
    "baselined_findings": 0,
    "severity_counts": {
      "high": 5,
      "medium": 11,
      "low": 0
    }
  },
  "filtering": {
    "total_findings": 16,
    "active_findings": 16,
    "suppressed_findings": 0,
    "baselined_findings": 0,
    "suppressions_path": null,
    "baseline_path": null
  },
  "inventory": {
    "provider": "aws",
    "unsupported_resources": [],
    "metadata": {
      "primary_account_id": "555566667777",
      "supported_resource_types": [
        "aws_db_instance",
        "aws_iam_instance_profile",
        "aws_iam_policy",
        "aws_iam_role",
        "aws_iam_role_policy",
        "aws_iam_role_policy_attachment",
        "aws_instance",
        "aws_internet_gateway",
        "aws_kms_key",
        "aws_lambda_function",
        "aws_lambda_permission",
        "aws_lb",
        "aws_nat_gateway",
        "aws_route_table",
        "aws_route_table_association",
        "aws_s3_bucket",
        "aws_s3_bucket_policy",
        "aws_s3_bucket_public_access_block",
        "aws_secretsmanager_secret",
        "aws_secretsmanager_secret_policy",
        "aws_security_group",
        "aws_security_group_rule",
        "aws_sns_topic",
        "aws_sqs_queue",
        "aws_subnet",
        "aws_vpc"
      ]
    },
    "resources": [
      {
        "address": "aws_db_instance.customer",
        "provider": "aws",
        "resource_type": "aws_db_instance",
        "name": "customer",
        "category": "data",
        "identifier": "db-bad-001",
        "arn": "arn:aws:rds:us-east-1:555566667777:db:nightmare-customer-db",
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [
          "sg-bad-db-001"
        ],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "engine": "postgres",
          "publicly_accessible": false,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "storage_encrypted": false,
          "db_subnet_group_name": "bad-private-data",
          "public_access_configured": false,
          "internet_ingress": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "aws_security_group.db ingress tcp 5432 from 0.0.0.0/0 (Postgres from internet)"
          ],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_iam_policy.admin_like",
        "provider": "aws",
        "resource_type": "aws_iam_policy",
        "name": "admin_like",
        "category": "iam",
        "identifier": "nightmare-admin-like",
        "arn": "arn:aws:iam::555566667777:policy/nightmare-admin-like",
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [
          {
            "effect": "Allow",
            "actions": [
              "ec2:*",
              "s3:*",
              "iam:*"
            ],
            "resources": [
              "*"
            ],
            "principals": [],
            "conditions": []
          }
        ],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "policy_document": {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Action": [
                  "ec2:*",
                  "s3:*",
                  "iam:*"
                ],
                "Resource": "*"
              }
            ]
          },
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_iam_role.app",
        "provider": "aws",
        "resource_type": "aws_iam_role",
        "name": "app",
        "category": "iam",
        "identifier": "nightmare-app-role",
        "arn": "arn:aws:iam::555566667777:role/nightmare-app-role",
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [
          {
            "effect": "Allow",
            "actions": [
              "*",
              "kms:Decrypt",
              "sts:AssumeRole"
            ],
            "resources": [
              "*"
            ],
            "principals": [],
            "conditions": []
          }
        ],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "assume_role_policy": {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Action": "sts:AssumeRole",
                "Principal": {
                  "Service": "lambda.amazonaws.com"
                }
              },
              {
                "Effect": "Allow",
                "Action": "sts:AssumeRole",
                "Principal": {
                  "AWS": "*"
                }
              }
            ]
          },
          "trust_principals": [
            "*",
            "lambda.amazonaws.com"
          ],
          "trust_statements": [
            {
              "principals": [
                "lambda.amazonaws.com"
              ],
              "narrowing_condition_keys": [],
              "narrowing_conditions": [],
              "has_narrowing_conditions": false
            },
            {
              "principals": [
                "*"
              ],
              "narrowing_condition_keys": [],
              "narrowing_conditions": [],
              "has_narrowing_conditions": false
            }
          ],
          "inline_policy_names": [
            "nightmare-app-inline"
          ],
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_iam_role.pipeline",
        "provider": "aws",
        "resource_type": "aws_iam_role",
        "name": "pipeline",
        "category": "iam",
        "identifier": "nightmare-pipeline-role",
        "arn": "arn:aws:iam::555566667777:role/nightmare-pipeline-role",
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [
          {
            "effect": "Allow",
            "actions": [
              "iam:*",
              "iam:PassRole",
              "s3:*"
            ],
            "resources": [
              "*"
            ],
            "principals": [],
            "conditions": []
          }
        ],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "assume_role_policy": {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Action": "sts:AssumeRole",
                "Principal": {
                  "Service": "lambda.amazonaws.com"
                }
              },
              {
                "Effect": "Allow",
                "Action": "sts:AssumeRole",
                "Principal": {
                  "AWS": "arn:aws:iam::444455556666:root"
                }
              }
            ]
          },
          "trust_principals": [
            "arn:aws:iam::444455556666:root",
            "lambda.amazonaws.com"
          ],
          "trust_statements": [
            {
              "principals": [
                "lambda.amazonaws.com"
              ],
              "narrowing_condition_keys": [],
              "narrowing_conditions": [],
              "has_narrowing_conditions": false
            },
            {
              "principals": [
                "arn:aws:iam::444455556666:root"
              ],
              "narrowing_condition_keys": [],
              "narrowing_conditions": [],
              "has_narrowing_conditions": false
            }
          ],
          "inline_policy_names": [
            "nightmare-pipeline-inline"
          ],
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_instance.admin",
        "provider": "aws",
        "resource_type": "aws_instance",
        "name": "admin",
        "category": "compute",
        "identifier": "i-bad-admin-001",
        "arn": "arn:aws:ec2:us-east-1:555566667777:instance/i-bad-admin-001",
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [
          "subnet-bad-public-001"
        ],
        "security_group_ids": [
          "sg-bad-admin-001"
        ],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "standard",
        "metadata": {
          "ami": "ami-bad-admin",
          "instance_type": "t3.micro",
          "associate_public_ip_address": true,
          "iam_instance_profile": null,
          "public_access_reasons": [
            "instance requests an associated public IP address"
          ],
          "public_exposure_reasons": [
            "instance has a public IP path and attached security groups allow internet ingress"
          ],
          "tags": {
            "Tier": "admin"
          },
          "public_access_configured": true,
          "internet_ingress": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "aws_security_group.admin ingress tcp 3389 from 0.0.0.0/0 (RDP from internet)"
          ],
          "public_subnet": true,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": true
        }
      },
      {
        "address": "aws_instance.frontend",
        "provider": "aws",
        "resource_type": "aws_instance",
        "name": "frontend",
        "category": "compute",
        "identifier": "i-bad-front-001",
        "arn": "arn:aws:ec2:us-east-1:555566667777:instance/i-bad-front-001",
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [
          "subnet-bad-public-001"
        ],
        "security_group_ids": [
          "sg-bad-front-001"
        ],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "standard",
        "metadata": {
          "ami": "ami-bad-frontend",
          "instance_type": "t3.micro",
          "associate_public_ip_address": true,
          "iam_instance_profile": null,
          "public_access_reasons": [
            "instance requests an associated public IP address"
          ],
          "public_exposure_reasons": [
            "instance has a public IP path and attached security groups allow internet ingress"
          ],
          "tags": {
            "Tier": "frontend"
          },
          "public_access_configured": true,
          "internet_ingress": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "aws_security_group.frontend ingress tcp 0-65535 from 0.0.0.0/0 (Everything from the internet)"
          ],
          "public_subnet": true,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": true
        }
      },
      {
        "address": "aws_internet_gateway.main",
        "provider": "aws",
        "resource_type": "aws_internet_gateway",
        "name": "main",
        "category": "network",
        "identifier": "igw-bad-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_lambda_function.deployer",
        "provider": "aws",
        "resource_type": "aws_lambda_function",
        "name": "deployer",
        "category": "compute",
        "identifier": "nightmare-deployer",
        "arn": "arn:aws:lambda:us-east-1:555566667777:function:nightmare-deployer",
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [
          "subnet-bad-private-ops-001"
        ],
        "security_group_ids": [
          "sg-bad-admin-001"
        ],
        "attached_role_arns": [
          "arn:aws:iam::555566667777:role/nightmare-pipeline-role"
        ],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "runtime": "python3.12",
          "handler": "handler.main",
          "vpc_enabled": true,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "aws_security_group.admin ingress tcp 3389 from 0.0.0.0/0 (RDP from internet)"
          ],
          "public_subnet": false,
          "has_nat_gateway_egress": true,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_lambda_function.processor",
        "provider": "aws",
        "resource_type": "aws_lambda_function",
        "name": "processor",
        "category": "compute",
        "identifier": "nightmare-processor",
        "arn": "arn:aws:lambda:us-east-1:555566667777:function:nightmare-processor",
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [
          "subnet-bad-private-ops-001"
        ],
        "security_group_ids": [
          "sg-bad-front-001"
        ],
        "attached_role_arns": [
          "arn:aws:iam::555566667777:role/nightmare-app-role"
        ],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "runtime": "python3.12",
          "handler": "handler.main",
          "vpc_enabled": true,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "aws_security_group.frontend ingress tcp 0-65535 from 0.0.0.0/0 (Everything from the internet)"
          ],
          "public_subnet": false,
          "has_nat_gateway_egress": true,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_lb.web",
        "provider": "aws",
        "resource_type": "aws_lb",
        "name": "web",
        "category": "edge",
        "identifier": "alb-bad-001",
        "arn": "arn:aws:elasticloadbalancing:us-east-1:555566667777:loadbalancer/app/nightmare-web/123456",
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [
          "subnet-bad-public-001"
        ],
        "security_group_ids": [
          "sg-bad-front-001"
        ],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "standard",
        "metadata": {
          "internal": false,
          "load_balancer_type": "application",
          "public_access_reasons": [
            "load balancer is configured as internet-facing"
          ],
          "public_exposure_reasons": [
            "load balancer is internet-facing and attached security groups allow internet ingress"
          ],
          "public_access_configured": true,
          "internet_ingress": true,
          "internet_ingress_capable": true,
          "internet_ingress_reasons": [
            "aws_security_group.frontend ingress tcp 0-65535 from 0.0.0.0/0 (Everything from the internet)"
          ],
          "public_subnet": true,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": true
        }
      },
      {
        "address": "aws_nat_gateway.main",
        "provider": "aws",
        "resource_type": "aws_nat_gateway",
        "name": "main",
        "category": "network",
        "identifier": "nat-bad-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [
          "subnet-bad-public-001"
        ],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "allocation_id": "eipalloc-bad-001",
          "connectivity_type": "public",
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": true,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_route_table.private",
        "provider": "aws",
        "resource_type": "aws_route_table",
        "name": "private",
        "category": "network",
        "identifier": "rtb-bad-private-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "routes": [
            {
              "cidr_block": "0.0.0.0/0",
              "nat_gateway_id": "nat-bad-001"
            }
          ],
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_route_table.public",
        "provider": "aws",
        "resource_type": "aws_route_table",
        "name": "public",
        "category": "network",
        "identifier": "rtb-bad-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "routes": [
            {
              "cidr_block": "0.0.0.0/0",
              "gateway_id": "igw-bad-001"
            }
          ],
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_route_table_association.private_data",
        "provider": "aws",
        "resource_type": "aws_route_table_association",
        "name": "private_data",
        "category": "network",
        "identifier": "rtassoc-bad-private-data-001",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "route_table_id": "rtb-bad-private-001",
          "subnet_id": "subnet-bad-private-data-001",
          "gateway_id": null,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_route_table_association.private_ops",
        "provider": "aws",
        "resource_type": "aws_route_table_association",
        "name": "private_ops",
        "category": "network",
        "identifier": "rtassoc-bad-private-ops-001",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "route_table_id": "rtb-bad-private-001",
          "subnet_id": "subnet-bad-private-ops-001",
          "gateway_id": null,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_route_table_association.public_web",
        "provider": "aws",
        "resource_type": "aws_route_table_association",
        "name": "public_web",
        "category": "network",
        "identifier": "rtassoc-bad-public-001",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "route_table_id": "rtb-bad-001",
          "subnet_id": "subnet-bad-public-001",
          "gateway_id": null,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_s3_bucket.assets",
        "provider": "aws",
        "resource_type": "aws_s3_bucket",
        "name": "assets",
        "category": "data",
        "identifier": "nightmare-assets",
        "arn": "arn:aws:s3:::nightmare-assets",
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [
          {
            "effect": "Allow",
            "actions": [
              "s3:GetObject"
            ],
            "resources": [
              "arn:aws:s3:::nightmare-assets/*"
            ],
            "principals": [
              "*"
            ],
            "conditions": []
          }
        ],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "sensitive",
        "metadata": {
          "bucket": "nightmare-assets",
          "acl": "public-read",
          "policy_document": {
            "Version": "2012-10-17",
            "Statement": [
              {
                "Effect": "Allow",
                "Principal": "*",
                "Action": [
                  "s3:GetObject"
                ],
                "Resource": "arn:aws:s3:::nightmare-assets/*"
              }
            ]
          },
          "public_access_reasons": [
            "bucket ACL `public-read` grants public access",
            "bucket policy allows anonymous access"
          ],
          "public_exposure_reasons": [
            "bucket ACL `public-read` grants public access",
            "bucket policy allows anonymous access"
          ],
          "public_access_configured": true,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": true
        }
      },
      {
        "address": "aws_s3_bucket.backups",
        "provider": "aws",
        "resource_type": "aws_s3_bucket",
        "name": "backups",
        "category": "data",
        "identifier": "nightmare-backups",
        "arn": "arn:aws:s3:::nightmare-backups",
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": true,
        "public_exposure": true,
        "data_sensitivity": "sensitive",
        "metadata": {
          "bucket": "nightmare-backups",
          "acl": "public-read-write",
          "policy_document": {},
          "public_access_reasons": [
            "bucket ACL `public-read-write` grants public access"
          ],
          "public_exposure_reasons": [
            "bucket ACL `public-read-write` grants public access"
          ],
          "public_access_configured": true,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": true
        }
      },
      {
        "address": "aws_security_group.admin",
        "provider": "aws",
        "resource_type": "aws_security_group",
        "name": "admin",
        "category": "network",
        "identifier": "sg-bad-admin-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [
          {
            "direction": "ingress",
            "protocol": "tcp",
            "from_port": 3389,
            "to_port": 3389,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": "RDP from internet"
          },
          {
            "direction": "egress",
            "protocol": "-1",
            "from_port": 0,
            "to_port": 0,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": null
          }
        ],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "description": "Remote admin directly from the internet",
          "group_name": "bad-admin-sg",
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_security_group.db",
        "provider": "aws",
        "resource_type": "aws_security_group",
        "name": "db",
        "category": "network",
        "identifier": "sg-bad-db-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [
          {
            "direction": "ingress",
            "protocol": "tcp",
            "from_port": 5432,
            "to_port": 5432,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": "Postgres from internet"
          },
          {
            "direction": "ingress",
            "protocol": "tcp",
            "from_port": 5432,
            "to_port": 5432,
            "cidr_blocks": [],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [
              "sg-bad-front-001",
              "sg-bad-admin-001"
            ],
            "description": "Postgres from public tiers"
          },
          {
            "direction": "egress",
            "protocol": "-1",
            "from_port": 0,
            "to_port": 0,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": null
          }
        ],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "description": "Database tier exposed to public and public app tiers",
          "group_name": "bad-db-sg",
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_security_group.frontend",
        "provider": "aws",
        "resource_type": "aws_security_group",
        "name": "frontend",
        "category": "network",
        "identifier": "sg-bad-front-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [
          {
            "direction": "ingress",
            "protocol": "tcp",
            "from_port": 0,
            "to_port": 65535,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": "Everything from the internet"
          },
          {
            "direction": "egress",
            "protocol": "-1",
            "from_port": 0,
            "to_port": 0,
            "cidr_blocks": [
              "0.0.0.0/0"
            ],
            "ipv6_cidr_blocks": [],
            "referenced_security_group_ids": [],
            "description": null
          }
        ],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "description": "Open frontend security group",
          "group_name": "bad-front-sg",
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_subnet.private_data",
        "provider": "aws",
        "resource_type": "aws_subnet",
        "name": "private_data",
        "category": "network",
        "identifier": "subnet-bad-private-data-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "cidr_block": "10.20.3.0/24",
          "availability_zone": "us-east-1a",
          "map_public_ip_on_launch": false,
          "tags": {
            "Tier": "data"
          },
          "is_public_subnet": false,
          "route_table_ids": [
            "rtb-bad-private-001"
          ],
          "has_public_route": false,
          "has_nat_gateway_egress": true,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_subnet.private_ops",
        "provider": "aws",
        "resource_type": "aws_subnet",
        "name": "private_ops",
        "category": "network",
        "identifier": "subnet-bad-private-ops-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "cidr_block": "10.20.2.0/24",
          "availability_zone": "us-east-1a",
          "map_public_ip_on_launch": false,
          "tags": {
            "Tier": "ops"
          },
          "is_public_subnet": false,
          "route_table_ids": [
            "rtb-bad-private-001"
          ],
          "has_public_route": false,
          "has_nat_gateway_egress": true,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_subnet.public_web",
        "provider": "aws",
        "resource_type": "aws_subnet",
        "name": "public_web",
        "category": "network",
        "identifier": "subnet-bad-public-001",
        "arn": null,
        "vpc_id": "vpc-bad-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "cidr_block": "10.20.1.0/24",
          "availability_zone": "us-east-1a",
          "map_public_ip_on_launch": true,
          "tags": {
            "Tier": "public"
          },
          "is_public_subnet": true,
          "route_table_ids": [
            "rtb-bad-001"
          ],
          "has_public_route": true,
          "has_nat_gateway_egress": false,
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_vpc.main",
        "provider": "aws",
        "resource_type": "aws_vpc",
        "name": "main",
        "category": "network",
        "identifier": "vpc-bad-001",
        "arn": null,
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "standard",
        "metadata": {
          "cidr_block": "10.20.0.0/16",
          "tags": {
            "Name": "nightmare-main"
          },
          "public_access_reasons": [],
          "public_exposure_reasons": [],
          "public_access_configured": false,
          "internet_ingress": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": false,
          "direct_internet_reachable": false
        }
      }
    ]
  },
  "trust_boundaries": [
    {
      "identifier": "admin-to-workload-plane:aws_iam_role.app->aws_lambda_function.processor",
      "boundary_type": "admin-to-workload-plane",
      "source": "aws_iam_role.app",
      "target": "aws_lambda_function.processor",
      "description": "aws_iam_role.app governs actions performed by aws_lambda_function.processor.",
      "rationale": "IAM configuration acts as a control-plane boundary because the workload inherits whatever privileges the role carries."
    },
    {
      "identifier": "admin-to-workload-plane:aws_iam_role.pipeline->aws_lambda_function.deployer",
      "boundary_type": "admin-to-workload-plane",
      "source": "aws_iam_role.pipeline",
      "target": "aws_lambda_function.deployer",
      "description": "aws_iam_role.pipeline governs actions performed by aws_lambda_function.deployer.",
      "rationale": "IAM configuration acts as a control-plane boundary because the workload inherits whatever privileges the role carries."
    },
    {
      "identifier": "cross-account-or-role-access:*->aws_iam_role.app",
      "boundary_type": "cross-account-or-role-access",
      "source": "*",
      "target": "aws_iam_role.app",
      "description": "aws_iam_role.app trusts any principal.",
      "rationale": "An additional role or principal can cross into this role's trust boundary."
    },
    {
      "identifier": "cross-account-or-role-access:arn:aws:iam::444455556666:root->aws_iam_role.pipeline",
      "boundary_type": "cross-account-or-role-access",
      "source": "arn:aws:iam::444455556666:root",
      "target": "aws_iam_role.pipeline",
      "description": "aws_iam_role.pipeline trusts arn:aws:iam::444455556666:root.",
      "rationale": "A foreign AWS account can cross into this role's trust boundary."
    },
    {
      "identifier": "internet-to-service:internet->aws_instance.admin",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "aws_instance.admin",
      "description": "Traffic can cross from the public internet to aws_instance.admin.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->aws_instance.frontend",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "aws_instance.frontend",
      "description": "Traffic can cross from the public internet to aws_instance.frontend.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->aws_lb.web",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "aws_lb.web",
      "description": "Traffic can cross from the public internet to aws_lb.web.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->aws_s3_bucket.assets",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "aws_s3_bucket.assets",
      "description": "Traffic can cross from the public internet to aws_s3_bucket.assets.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "internet-to-service:internet->aws_s3_bucket.backups",
      "boundary_type": "internet-to-service",
      "source": "internet",
      "target": "aws_s3_bucket.backups",
      "description": "Traffic can cross from the public internet to aws_s3_bucket.backups.",
      "rationale": "The resource is directly reachable or intentionally exposed to unauthenticated network clients."
    },
    {
      "identifier": "public-subnet-to-private-subnet:aws_subnet.public_web->aws_subnet.private_data",
      "boundary_type": "public-subnet-to-private-subnet",
      "source": "aws_subnet.public_web",
      "target": "aws_subnet.private_data",
      "description": "Traffic can move from aws_subnet.public_web toward aws_subnet.private_data.",
      "rationale": "The VPC contains both publicly routable and private network segments that should be treated as separate trust zones."
    },
    {
      "identifier": "public-subnet-to-private-subnet:aws_subnet.public_web->aws_subnet.private_ops",
      "boundary_type": "public-subnet-to-private-subnet",
      "source": "aws_subnet.public_web",
      "target": "aws_subnet.private_ops",
      "description": "Traffic can move from aws_subnet.public_web toward aws_subnet.private_ops.",
      "rationale": "The VPC contains both publicly routable and private network segments that should be treated as separate trust zones."
    },
    {
      "identifier": "workload-to-data-store:aws_instance.admin->aws_db_instance.customer",
      "boundary_type": "workload-to-data-store",
      "source": "aws_instance.admin",
      "target": "aws_db_instance.customer",
      "description": "aws_instance.admin can interact with aws_db_instance.customer.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group."
    },
    {
      "identifier": "workload-to-data-store:aws_instance.frontend->aws_db_instance.customer",
      "boundary_type": "workload-to-data-store",
      "source": "aws_instance.frontend",
      "target": "aws_db_instance.customer",
      "description": "aws_instance.frontend can interact with aws_db_instance.customer.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group."
    },
    {
      "identifier": "workload-to-data-store:aws_lambda_function.deployer->aws_db_instance.customer",
      "boundary_type": "workload-to-data-store",
      "source": "aws_lambda_function.deployer",
      "target": "aws_db_instance.customer",
      "description": "aws_lambda_function.deployer can interact with aws_db_instance.customer.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group."
    },
    {
      "identifier": "workload-to-data-store:aws_lambda_function.deployer->aws_s3_bucket.assets",
      "boundary_type": "workload-to-data-store",
      "source": "aws_lambda_function.deployer",
      "target": "aws_s3_bucket.assets",
      "description": "aws_lambda_function.deployer can interact with aws_s3_bucket.assets.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:*."
    },
    {
      "identifier": "workload-to-data-store:aws_lambda_function.deployer->aws_s3_bucket.backups",
      "boundary_type": "workload-to-data-store",
      "source": "aws_lambda_function.deployer",
      "target": "aws_s3_bucket.backups",
      "description": "aws_lambda_function.deployer can interact with aws_s3_bucket.backups.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:*."
    },
    {
      "identifier": "workload-to-data-store:aws_lambda_function.processor->aws_db_instance.customer",
      "boundary_type": "workload-to-data-store",
      "source": "aws_lambda_function.processor",
      "target": "aws_db_instance.customer",
      "description": "aws_lambda_function.processor can interact with aws_db_instance.customer.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group."
    },
    {
      "identifier": "workload-to-data-store:aws_lambda_function.processor->aws_s3_bucket.assets",
      "boundary_type": "workload-to-data-store",
      "source": "aws_lambda_function.processor",
      "target": "aws_s3_bucket.assets",
      "description": "aws_lambda_function.processor can interact with aws_s3_bucket.assets.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as *."
    },
    {
      "identifier": "workload-to-data-store:aws_lambda_function.processor->aws_s3_bucket.backups",
      "boundary_type": "workload-to-data-store",
      "source": "aws_lambda_function.processor",
      "target": "aws_s3_bucket.backups",
      "description": "aws_lambda_function.processor can interact with aws_s3_bucket.backups.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as *."
    }
  ],
  "findings": [
    {
      "fingerprint": "sha256:6d4643ee1a3fbae62bfa658ed1b46d42a16413fc7f66598ac4bd2e5badeae8da",
      "title": "Database is reachable from overly permissive sources",
      "rule_id": "aws-database-permissive-ingress",
      "category": "Information Disclosure",
      "severity": "high",
      "affected_resources": [
        "aws_db_instance.customer",
        "aws_security_group.db"
      ],
      "trust_boundary_id": "workload-to-data-store:aws_instance.admin->aws_db_instance.customer",
      "rationale": "aws_db_instance.customer is a sensitive data store, but database is not marked directly internet reachable, but its security groups allow internet-origin ingress, and database trusts security groups attached to internet-exposed workloads. That weakens the expected separation between the workload tier and the data tier.",
      "recommended_mitigation": "Keep databases off public paths, allow ingress only from narrowly scoped application security groups, and enforce authentication plus encryption independently of network policy.",
      "evidence": [
        {
          "key": "security_group_rules",
          "values": [
            "aws_security_group.db ingress tcp 5432 from 0.0.0.0/0 (Postgres from internet)",
            "aws_security_group.db ingress tcp 5432 from sg-bad-admin-001, sg-bad-front-001 (Postgres from public tiers)"
          ]
        },
        {
          "key": "network_path",
          "values": [
            "database is not marked directly internet reachable, but its security groups allow internet-origin ingress",
            "database trusts security groups attached to internet-exposed workloads",
            "aws_security_group.db allows sg-bad-front-001, sg-bad-admin-001 attached to aws_instance.admin, aws_instance.frontend, aws_lb.web"
          ]
        },
        {
          "key": "subnet_posture",
          "values": [
            "aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route",
            "aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route",
            "aws_lb.web sits in public subnet aws_subnet.public_web with an internet route"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:aeea49bad92e77900d646bfbfeb717cf1f07d1c7cbcb49fa6c8a3b93833d2aa7",
      "title": "Private data tier directly trusts the public application tier",
      "rule_id": "aws-missing-tier-segmentation",
      "category": "Tampering",
      "severity": "high",
      "affected_resources": [
        "aws_db_instance.customer",
        "aws_instance.admin",
        "aws_instance.frontend",
        "aws_lb.web",
        "aws_security_group.db"
      ],
      "trust_boundary_id": "public-subnet-to-private-subnet:aws_subnet.public_web->aws_subnet.private_ops",
      "rationale": "aws_db_instance.customer accepts traffic from security groups attached to internet-facing workloads. A compromise of the public tier can therefore move laterally into the private data tier.",
      "recommended_mitigation": "Introduce tighter tier segmentation with dedicated security groups, narrow ingress to specific services and ports, and keep the data tier reachable only through controlled application paths.",
      "evidence": [
        {
          "key": "security_group_rules",
          "values": [
            "aws_security_group.db ingress tcp 5432 from sg-bad-admin-001, sg-bad-front-001 (Postgres from public tiers)"
          ]
        },
        {
          "key": "network_path",
          "values": [
            "aws_security_group.db allows sg-bad-front-001, sg-bad-admin-001 attached to aws_instance.admin, aws_instance.frontend, aws_lb.web"
          ]
        },
        {
          "key": "subnet_posture",
          "values": [
            "aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route",
            "aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route",
            "aws_lb.web sits in public subnet aws_subnet.public_web with an internet route"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 2,
        "blast_radius": 1,
        "final_score": 7,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:904c35dfdbde239002ef052d7c81125465304df7a61116347657e2597f19ad39",
      "title": "Role trust relationship expands blast radius",
      "rule_id": "aws-role-trust-expansion",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "aws_iam_role.app"
      ],
      "trust_boundary_id": "cross-account-or-role-access:*->aws_iam_role.app",
      "rationale": "aws_iam_role.app can be assumed by *. Broad or foreign-account trust relationships increase the chance that compromise in one identity domain spills into another.",
      "recommended_mitigation": "Limit trust policies to the exact service principals or roles required, prefer role ARNs over account root where possible, and add conditions such as `ExternalId` or source ARN checks.",
      "evidence": [
        {
          "key": "trust_principals",
          "values": [
            "*"
          ]
        },
        {
          "key": "trust_path",
          "values": [
            "trust policy allows any AWS principal"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:23b93d86320e4600396004bc9c01fcec86302bdff1246fff3f47bd9acc6fe68b",
      "title": "Workload role carries sensitive permissions",
      "rule_id": "aws-workload-role-sensitive-permissions",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "aws_lambda_function.processor",
        "aws_iam_role.app"
      ],
      "trust_boundary_id": "admin-to-workload-plane:aws_iam_role.app->aws_lambda_function.processor",
      "rationale": "aws_lambda_function.processor inherits sensitive privileges from aws_iam_role.app, including *, kms:Decrypt, sts:AssumeRole. If the workload is compromised, those credentials can be reused for privilege escalation, data access, or role chaining.",
      "recommended_mitigation": "Split high-privilege actions into separate roles, scope permissions to named resources, and remove role-passing or cross-role permissions from general application identities.",
      "evidence": [
        {
          "key": "iam_actions",
          "values": [
            "*",
            "kms:Decrypt",
            "sts:AssumeRole"
          ]
        },
        {
          "key": "policy_statements",
          "values": [
            "Allow actions=[*, kms:Decrypt, sts:AssumeRole] resources=[*]"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 1,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:c959fb0b0e809165c19da8673b7737bd5addf4a164d9efa79bef5237e20c356b",
      "title": "Workload role carries sensitive permissions",
      "rule_id": "aws-workload-role-sensitive-permissions",
      "category": "Elevation of Privilege",
      "severity": "high",
      "affected_resources": [
        "aws_lambda_function.deployer",
        "aws_iam_role.pipeline"
      ],
      "trust_boundary_id": "admin-to-workload-plane:aws_iam_role.pipeline->aws_lambda_function.deployer",
      "rationale": "aws_lambda_function.deployer inherits sensitive privileges from aws_iam_role.pipeline, including iam:PassRole, s3:*. If the workload is compromised, those credentials can be reused for privilege escalation, data access, or role chaining.",
      "recommended_mitigation": "Split high-privilege actions into separate roles, scope permissions to named resources, and remove role-passing or cross-role permissions from general application identities.",
      "evidence": [
        {
          "key": "iam_actions",
          "values": [
            "iam:PassRole",
            "s3:*"
          ]
        },
        {
          "key": "policy_statements",
          "values": [
            "Allow actions=[iam:*, iam:PassRole, s3:*] resources=[*]"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 1,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 6,
        "severity": "high",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:6c7ce0e46a8e03165c15db71257c14b20c8af6ecaca602b34b2a1b3df57d9aaf",
      "title": "Cross-account or broad role trust lacks narrowing conditions",
      "rule_id": "aws-role-trust-missing-narrowing",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_iam_role.app"
      ],
      "trust_boundary_id": "cross-account-or-role-access:*->aws_iam_role.app",
      "rationale": "aws_iam_role.app trusts * without supported narrowing conditions such as `sts:ExternalId`, `aws:SourceArn`, or `aws:SourceAccount`. That leaves the assume-role path dependent on a broad or external principal match alone.",
      "recommended_mitigation": "Keep the trusted principal as specific as possible and add supported assume-role conditions such as `ExternalId`, `SourceArn`, or `SourceAccount` when crossing accounts or trusting broad principals.",
      "evidence": [
        {
          "key": "trust_principals",
          "values": [
            "*"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "principal is wildcard"
          ]
        },
        {
          "key": "trust_narrowing",
          "values": [
            "supported narrowing conditions present: false",
            "supported narrowing condition keys: none"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:c9c42ef2b22af6aabee815edcb2262610e36987dde1c2053de82ab79156f542d",
      "title": "Cross-account or broad role trust lacks narrowing conditions",
      "rule_id": "aws-role-trust-missing-narrowing",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_iam_role.pipeline"
      ],
      "trust_boundary_id": "cross-account-or-role-access:arn:aws:iam::444455556666:root->aws_iam_role.pipeline",
      "rationale": "aws_iam_role.pipeline trusts arn:aws:iam::444455556666:root without supported narrowing conditions such as `sts:ExternalId`, `aws:SourceArn`, or `aws:SourceAccount`. That leaves the assume-role path dependent on a broad or external principal match alone.",
      "recommended_mitigation": "Keep the trusted principal as specific as possible and add supported assume-role conditions such as `ExternalId`, `SourceArn`, or `SourceAccount` when crossing accounts or trusting broad principals.",
      "evidence": [
        {
          "key": "trust_principals",
          "values": [
            "arn:aws:iam::444455556666:root"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "principal is foreign account root 444455556666"
          ]
        },
        {
          "key": "trust_narrowing",
          "values": [
            "supported narrowing conditions present: false",
            "supported narrowing condition keys: none"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:4fcd3f97155279eba0b099fc8f1e717c55ef2dfcbb383b7c6423dc35a370314f",
      "title": "Database storage encryption is disabled",
      "rule_id": "aws-rds-storage-encryption-disabled",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "aws_db_instance.customer"
      ],
      "trust_boundary_id": null,
      "rationale": "aws_db_instance.customer stores sensitive data, but `storage_encrypted` is disabled. That weakens data-at-rest protections for underlying storage, snapshots, and backup handling.",
      "recommended_mitigation": "Enable RDS storage encryption with a managed KMS key, enforce encryption by default in database modules, and migrate plaintext instances to encrypted replacements where needed.",
      "evidence": [
        {
          "key": "encryption_posture",
          "values": [
            "storage_encrypted is false",
            "engine is postgres"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 3,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:bb1291457d93a36d39aed5ae733f7b5826cb5bd4d85e24275f5bcce012c78832",
      "title": "IAM policy grants wildcard privileges",
      "rule_id": "aws-iam-wildcard-permissions",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_iam_role.app"
      ],
      "trust_boundary_id": null,
      "rationale": "aws_iam_role.app contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.",
      "recommended_mitigation": "Replace wildcard actions and resources with narrowly scoped permissions tied to the exact services, APIs, and ARNs required by the workload.",
      "evidence": [
        {
          "key": "iam_actions",
          "values": [
            "*"
          ]
        },
        {
          "key": "iam_resources",
          "values": [
            "*"
          ]
        },
        {
          "key": "policy_statements",
          "values": [
            "Allow actions=[*, kms:Decrypt, sts:AssumeRole] resources=[*]"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:80cbdcf6218896a14f6042288b83f6b71e3fa5a1a3eb77008574b526a5c52752",
      "title": "IAM policy grants wildcard privileges",
      "rule_id": "aws-iam-wildcard-permissions",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_iam_role.pipeline"
      ],
      "trust_boundary_id": null,
      "rationale": "aws_iam_role.pipeline contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.",
      "recommended_mitigation": "Replace wildcard actions and resources with narrowly scoped permissions tied to the exact services, APIs, and ARNs required by the workload.",
      "evidence": [
        {
          "key": "iam_actions",
          "values": [
            "iam:*",
            "s3:*"
          ]
        },
        {
          "key": "iam_resources",
          "values": [
            "*"
          ]
        },
        {
          "key": "policy_statements",
          "values": [
            "Allow actions=[iam:*, iam:PassRole, s3:*] resources=[*]"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:71b5e5c5fe134d3fb9a78dfeea85c7bc76adcf129c6850f68e7903e91e15dcb6",
      "title": "IAM policy grants wildcard privileges",
      "rule_id": "aws-iam-wildcard-permissions",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_iam_policy.admin_like"
      ],
      "trust_boundary_id": null,
      "rationale": "aws_iam_policy.admin_like contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.",
      "recommended_mitigation": "Replace wildcard actions and resources with narrowly scoped permissions tied to the exact services, APIs, and ARNs required by the workload.",
      "evidence": [
        {
          "key": "iam_actions",
          "values": [
            "ec2:*",
            "iam:*",
            "s3:*"
          ]
        },
        {
          "key": "iam_resources",
          "values": [
            "*"
          ]
        },
        {
          "key": "policy_statements",
          "values": [
            "Allow actions=[ec2:*, s3:*, iam:*] resources=[*]"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 2,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:14d80be77bd95012e23371d65c99a8f664aede75b7a29997665fed57a20a313e",
      "title": "Internet-exposed compute service permits overly broad ingress",
      "rule_id": "aws-public-compute-broad-ingress",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "aws_instance.frontend",
        "aws_security_group.frontend"
      ],
      "trust_boundary_id": "internet-to-service:internet->aws_instance.frontend",
      "rationale": "aws_instance.frontend is reachable from the internet and at least one attached security group allows administrative access or all ports from 0.0.0.0/0. That broad ingress raises the chance of unauthenticated probing and credential attacks.",
      "recommended_mitigation": "Restrict ingress to expected client ports, remove direct administrative exposure, and place management access behind a controlled bastion, VPN, or SSM Session Manager.",
      "evidence": [
        {
          "key": "security_group_rules",
          "values": [
            "aws_security_group.frontend ingress tcp 0-65535 from 0.0.0.0/0 (Everything from the internet)"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "instance has a public IP path and attached security groups allow internet ingress"
          ]
        },
        {
          "key": "subnet_posture",
          "values": [
            "aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 4,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:835976b372cdbf99fee4a2eaff8958c715496a1cca1b8c5bd4012bf1ed132924",
      "title": "Internet-exposed compute service permits overly broad ingress",
      "rule_id": "aws-public-compute-broad-ingress",
      "category": "Spoofing",
      "severity": "medium",
      "affected_resources": [
        "aws_instance.admin",
        "aws_security_group.admin"
      ],
      "trust_boundary_id": "internet-to-service:internet->aws_instance.admin",
      "rationale": "aws_instance.admin is reachable from the internet and at least one attached security group allows administrative access or all ports from 0.0.0.0/0. That broad ingress raises the chance of unauthenticated probing and credential attacks.",
      "recommended_mitigation": "Restrict ingress to expected client ports, remove direct administrative exposure, and place management access behind a controlled bastion, VPN, or SSM Session Manager.",
      "evidence": [
        {
          "key": "security_group_rules",
          "values": [
            "aws_security_group.admin ingress tcp 3389 from 0.0.0.0/0 (RDP from internet)"
          ]
        },
        {
          "key": "public_exposure_reasons",
          "values": [
            "instance has a public IP path and attached security groups allow internet ingress"
          ]
        },
        {
          "key": "subnet_posture",
          "values": [
            "aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 1,
        "final_score": 4,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:d22d3154af323df338d9e2592b1be16eaa6da2956113e6177b7e932c2898a9e4",
      "title": "Object storage is publicly accessible",
      "rule_id": "aws-s3-public-access",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "aws_s3_bucket.assets"
      ],
      "trust_boundary_id": "internet-to-service:internet->aws_s3_bucket.assets",
      "rationale": "aws_s3_bucket.assets appears to be public through ACLs or bucket policy. Public object access is a common source of unintended data disclosure.",
      "recommended_mitigation": "Remove public ACL or bucket policy access, enable an S3 public access block, and serve content through a controlled CDN or origin access pattern when public distribution is required.",
      "evidence": [
        {
          "key": "public_exposure_reasons",
          "values": [
            "bucket ACL `public-read` grants public access",
            "bucket policy allows anonymous access"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:03e2c7c12cd825ff8e1b46802b15478142ce385a1443056ff5d8dbbefdc8a04c",
      "title": "Object storage is publicly accessible",
      "rule_id": "aws-s3-public-access",
      "category": "Information Disclosure",
      "severity": "medium",
      "affected_resources": [
        "aws_s3_bucket.backups"
      ],
      "trust_boundary_id": "internet-to-service:internet->aws_s3_bucket.backups",
      "rationale": "aws_s3_bucket.backups appears to be public through ACLs or bucket policy. Public object access is a common source of unintended data disclosure.",
      "recommended_mitigation": "Remove public ACL or bucket policy access, enable an S3 public access block, and serve content through a controlled CDN or origin access pattern when public distribution is required.",
      "evidence": [
        {
          "key": "public_exposure_reasons",
          "values": [
            "bucket ACL `public-read-write` grants public access"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 2,
        "privilege_breadth": 0,
        "data_sensitivity": 2,
        "lateral_movement": 0,
        "blast_radius": 1,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:22ea0a3acb79fc019c9a8994082fc8b5262fff425980cd9d24fb783c49d0a890",
      "title": "Role trust relationship expands blast radius",
      "rule_id": "aws-role-trust-expansion",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_iam_role.pipeline"
      ],
      "trust_boundary_id": "cross-account-or-role-access:arn:aws:iam::444455556666:root->aws_iam_role.pipeline",
      "rationale": "aws_iam_role.pipeline can be assumed by arn:aws:iam::444455556666:root. Broad or foreign-account trust relationships increase the chance that compromise in one identity domain spills into another.",
      "recommended_mitigation": "Limit trust policies to the exact service principals or roles required, prefer role ARNs over account root where possible, and add conditions such as `ExternalId` or source ARN checks.",
      "evidence": [
        {
          "key": "trust_principals",
          "values": [
            "arn:aws:iam::444455556666:root"
          ]
        },
        {
          "key": "trust_path",
          "values": [
            "trust principal belongs to foreign account 444455556666"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 1,
        "data_sensitivity": 0,
        "lateral_movement": 2,
        "blast_radius": 2,
        "final_score": 5,
        "severity": "medium",
        "computed_severity": null
      }
    }
  ],
  "suppressed_findings": [],
  "baselined_findings": [],
  "observations": [],
  "limitations": [
    "AWS support is intentionally limited to a curated v1 resource set rather than the full Terraform AWS provider.",
    "Subnet public/private classification prefers explicit route table associations and NAT or internet routes when present, but it does not model main-route-table inheritance or every routing edge case.",
    "IAM analysis resolves inline role policies, customer-managed role-policy attachments, and EC2 instance profiles present in the plan, but it does not expand AWS-managed policy documents that are not materialized in Terraform state.",
    "Resource-policy analysis focuses on explicit policy documents and Lambda permission resources present in the plan; it does not model every service-specific condition key or every downstream runtime authorization path.",
    "The engine reasons over Terraform planned values only and does not validate runtime drift, CloudTrail evidence, or post-deploy control-plane activity."
  ]
}
Markdown report
# Nightmare Plan Demo

- Analyzed file: `sample_aws_nightmare_plan.json`
- Provider: `aws`
- Normalized resources: `25`
- Unsupported resources: `0`

## Summary

This run identified **19 trust boundaries** and **16 findings** across **25 normalized resources**.

- High severity findings: `5`
- Medium severity findings: `11`
- Low severity findings: `0`

## Discovered Trust Boundaries

### `internet-to-service`

- Source: `internet`
- Target: `aws_lb.web`
- Description: Traffic can cross from the public internet to aws_lb.web.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `aws_instance.frontend`
- Description: Traffic can cross from the public internet to aws_instance.frontend.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `aws_instance.admin`
- Description: Traffic can cross from the public internet to aws_instance.admin.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `aws_s3_bucket.assets`
- Description: Traffic can cross from the public internet to aws_s3_bucket.assets.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `internet-to-service`

- Source: `internet`
- Target: `aws_s3_bucket.backups`
- Description: Traffic can cross from the public internet to aws_s3_bucket.backups.
- Rationale: The resource is directly reachable or intentionally exposed to unauthenticated network clients.

### `public-subnet-to-private-subnet`

- Source: `aws_subnet.public_web`
- Target: `aws_subnet.private_ops`
- Description: Traffic can move from aws_subnet.public_web toward aws_subnet.private_ops.
- Rationale: The VPC contains both publicly routable and private network segments that should be treated as separate trust zones.

### `public-subnet-to-private-subnet`

- Source: `aws_subnet.public_web`
- Target: `aws_subnet.private_data`
- Description: Traffic can move from aws_subnet.public_web toward aws_subnet.private_data.
- Rationale: The VPC contains both publicly routable and private network segments that should be treated as separate trust zones.

### `workload-to-data-store`

- Source: `aws_instance.frontend`
- Target: `aws_db_instance.customer`
- Description: aws_instance.frontend can interact with aws_db_instance.customer.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

### `workload-to-data-store`

- Source: `aws_instance.admin`
- Target: `aws_db_instance.customer`
- Description: aws_instance.admin can interact with aws_db_instance.customer.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

### `workload-to-data-store`

- Source: `aws_lambda_function.processor`
- Target: `aws_db_instance.customer`
- Description: aws_lambda_function.processor can interact with aws_db_instance.customer.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

### `workload-to-data-store`

- Source: `aws_lambda_function.processor`
- Target: `aws_s3_bucket.assets`
- Description: aws_lambda_function.processor can interact with aws_s3_bucket.assets.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as *.

### `workload-to-data-store`

- Source: `aws_lambda_function.processor`
- Target: `aws_s3_bucket.backups`
- Description: aws_lambda_function.processor can interact with aws_s3_bucket.backups.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as *.

### `admin-to-workload-plane`

- Source: `aws_iam_role.app`
- Target: `aws_lambda_function.processor`
- Description: aws_iam_role.app governs actions performed by aws_lambda_function.processor.
- Rationale: IAM configuration acts as a control-plane boundary because the workload inherits whatever privileges the role carries.

### `workload-to-data-store`

- Source: `aws_lambda_function.deployer`
- Target: `aws_db_instance.customer`
- Description: aws_lambda_function.deployer can interact with aws_db_instance.customer.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when database ingress security groups explicitly trust the workload security group.

### `workload-to-data-store`

- Source: `aws_lambda_function.deployer`
- Target: `aws_s3_bucket.assets`
- Description: aws_lambda_function.deployer can interact with aws_s3_bucket.assets.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:*.

### `workload-to-data-store`

- Source: `aws_lambda_function.deployer`
- Target: `aws_s3_bucket.backups`
- Description: aws_lambda_function.deployer can interact with aws_s3_bucket.backups.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:*.

### `admin-to-workload-plane`

- Source: `aws_iam_role.pipeline`
- Target: `aws_lambda_function.deployer`
- Description: aws_iam_role.pipeline governs actions performed by aws_lambda_function.deployer.
- Rationale: IAM configuration acts as a control-plane boundary because the workload inherits whatever privileges the role carries.

### `cross-account-or-role-access`

- Source: `*`
- Target: `aws_iam_role.app`
- Description: aws_iam_role.app trusts any principal.
- Rationale: An additional role or principal can cross into this role's trust boundary.

### `cross-account-or-role-access`

- Source: `arn:aws:iam::444455556666:root`
- Target: `aws_iam_role.pipeline`
- Description: aws_iam_role.pipeline trusts arn:aws:iam::444455556666:root.
- Rationale: A foreign AWS account can cross into this role's trust boundary.

## Findings

### High

#### Database is reachable from overly permissive sources

- STRIDE category: Information Disclosure
- Affected resources: `aws_db_instance.customer`, `aws_security_group.db`
- Trust boundary: `workload-to-data-store:aws_instance.admin->aws_db_instance.customer`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +1, blast_radius +1, final_score 6 => high
- Rationale: aws_db_instance.customer is a sensitive data store, but database is not marked directly internet reachable, but its security groups allow internet-origin ingress, and database trusts security groups attached to internet-exposed workloads. That weakens the expected separation between the workload tier and the data tier.
- Recommended mitigation: Keep databases off public paths, allow ingress only from narrowly scoped application security groups, and enforce authentication plus encryption independently of network policy.
- Evidence:
  - security group rules: aws_security_group.db ingress tcp 5432 from 0.0.0.0/0 (Postgres from internet); aws_security_group.db ingress tcp 5432 from sg-bad-admin-001, sg-bad-front-001 (Postgres from public tiers)
  - network path: database is not marked directly internet reachable, but its security groups allow internet-origin ingress; database trusts security groups attached to internet-exposed workloads; aws_security_group.db allows sg-bad-front-001, sg-bad-admin-001 attached to aws_instance.admin, aws_instance.frontend, aws_lb.web
  - subnet posture: aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route; aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route; aws_lb.web sits in public subnet aws_subnet.public_web with an internet route

#### Private data tier directly trusts the public application tier

- STRIDE category: Tampering
- Affected resources: `aws_db_instance.customer`, `aws_instance.admin`, `aws_instance.frontend`, `aws_lb.web`, `aws_security_group.db`
- Trust boundary: `public-subnet-to-private-subnet:aws_subnet.public_web->aws_subnet.private_ops`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +2, blast_radius +1, final_score 7 => high
- Rationale: aws_db_instance.customer accepts traffic from security groups attached to internet-facing workloads. A compromise of the public tier can therefore move laterally into the private data tier.
- Recommended mitigation: Introduce tighter tier segmentation with dedicated security groups, narrow ingress to specific services and ports, and keep the data tier reachable only through controlled application paths.
- Evidence:
  - security group rules: aws_security_group.db ingress tcp 5432 from sg-bad-admin-001, sg-bad-front-001 (Postgres from public tiers)
  - network path: aws_security_group.db allows sg-bad-front-001, sg-bad-admin-001 attached to aws_instance.admin, aws_instance.frontend, aws_lb.web
  - subnet posture: aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route; aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route; aws_lb.web sits in public subnet aws_subnet.public_web with an internet route

#### Role trust relationship expands blast radius

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.app`
- Trust boundary: `cross-account-or-role-access:*->aws_iam_role.app`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +2, blast_radius +2, final_score 6 => high
- Rationale: aws_iam_role.app can be assumed by *. Broad or foreign-account trust relationships increase the chance that compromise in one identity domain spills into another.
- Recommended mitigation: Limit trust policies to the exact service principals or roles required, prefer role ARNs over account root where possible, and add conditions such as `ExternalId` or source ARN checks.
- Evidence:
  - trust principals: *
  - trust path: trust policy allows any AWS principal

#### Workload role carries sensitive permissions

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_lambda_function.processor`, `aws_iam_role.app`
- Trust boundary: `admin-to-workload-plane:aws_iam_role.app->aws_lambda_function.processor`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +1, lateral_movement +1, blast_radius +2, final_score 6 => high
- Rationale: aws_lambda_function.processor inherits sensitive privileges from aws_iam_role.app, including *, kms:Decrypt, sts:AssumeRole. If the workload is compromised, those credentials can be reused for privilege escalation, data access, or role chaining.
- Recommended mitigation: Split high-privilege actions into separate roles, scope permissions to named resources, and remove role-passing or cross-role permissions from general application identities.
- Evidence:
  - iam actions: *; kms:Decrypt; sts:AssumeRole
  - policy statements: Allow actions=[*, kms:Decrypt, sts:AssumeRole] resources=[*]

#### Workload role carries sensitive permissions

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_lambda_function.deployer`, `aws_iam_role.pipeline`
- Trust boundary: `admin-to-workload-plane:aws_iam_role.pipeline->aws_lambda_function.deployer`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +1, lateral_movement +1, blast_radius +2, final_score 6 => high
- Rationale: aws_lambda_function.deployer inherits sensitive privileges from aws_iam_role.pipeline, including iam:PassRole, s3:*. If the workload is compromised, those credentials can be reused for privilege escalation, data access, or role chaining.
- Recommended mitigation: Split high-privilege actions into separate roles, scope permissions to named resources, and remove role-passing or cross-role permissions from general application identities.
- Evidence:
  - iam actions: iam:PassRole; s3:*
  - policy statements: Allow actions=[iam:*, iam:PassRole, s3:*] resources=[*]

### Medium

#### Cross-account or broad role trust lacks narrowing conditions

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.app`
- Trust boundary: `cross-account-or-role-access:*->aws_iam_role.app`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +1, blast_radius +2, final_score 5 => medium
- Rationale: aws_iam_role.app trusts * without supported narrowing conditions such as `sts:ExternalId`, `aws:SourceArn`, or `aws:SourceAccount`. That leaves the assume-role path dependent on a broad or external principal match alone.
- Recommended mitigation: Keep the trusted principal as specific as possible and add supported assume-role conditions such as `ExternalId`, `SourceArn`, or `SourceAccount` when crossing accounts or trusting broad principals.
- Evidence:
  - trust principals: *
  - trust scope: principal is wildcard
  - trust narrowing: supported narrowing conditions present: false; supported narrowing condition keys: none

#### Cross-account or broad role trust lacks narrowing conditions

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.pipeline`
- Trust boundary: `cross-account-or-role-access:arn:aws:iam::444455556666:root->aws_iam_role.pipeline`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +1, blast_radius +2, final_score 5 => medium
- Rationale: aws_iam_role.pipeline trusts arn:aws:iam::444455556666:root without supported narrowing conditions such as `sts:ExternalId`, `aws:SourceArn`, or `aws:SourceAccount`. That leaves the assume-role path dependent on a broad or external principal match alone.
- Recommended mitigation: Keep the trusted principal as specific as possible and add supported assume-role conditions such as `ExternalId`, `SourceArn`, or `SourceAccount` when crossing accounts or trusting broad principals.
- Evidence:
  - trust principals: arn:aws:iam::444455556666:root
  - trust scope: principal is foreign account root 444455556666
  - trust narrowing: supported narrowing conditions present: false; supported narrowing condition keys: none

#### Database storage encryption is disabled

- STRIDE category: Information Disclosure
- Affected resources: `aws_db_instance.customer`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 3 => medium
- Rationale: aws_db_instance.customer stores sensitive data, but `storage_encrypted` is disabled. That weakens data-at-rest protections for underlying storage, snapshots, and backup handling.
- Recommended mitigation: Enable RDS storage encryption with a managed KMS key, enforce encryption by default in database modules, and migrate plaintext instances to encrypted replacements where needed.
- Evidence:
  - encryption posture: storage_encrypted is false; engine is postgres

#### IAM policy grants wildcard privileges

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.app`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +1, blast_radius +2, final_score 5 => medium
- Rationale: aws_iam_role.app contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.
- Recommended mitigation: Replace wildcard actions and resources with narrowly scoped permissions tied to the exact services, APIs, and ARNs required by the workload.
- Evidence:
  - iam actions: *
  - iam resources: *
  - policy statements: Allow actions=[*, kms:Decrypt, sts:AssumeRole] resources=[*]

#### IAM policy grants wildcard privileges

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.pipeline`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +1, blast_radius +2, final_score 5 => medium
- Rationale: aws_iam_role.pipeline contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.
- Recommended mitigation: Replace wildcard actions and resources with narrowly scoped permissions tied to the exact services, APIs, and ARNs required by the workload.
- Evidence:
  - iam actions: iam:*; s3:*
  - iam resources: *
  - policy statements: Allow actions=[iam:*, iam:PassRole, s3:*] resources=[*]

#### IAM policy grants wildcard privileges

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_policy.admin_like`
- Trust boundary: `not-applicable`
- Severity reasoning: internet_exposure +0, privilege_breadth +2, data_sensitivity +0, lateral_movement +1, blast_radius +2, final_score 5 => medium
- Rationale: aws_iam_policy.admin_like contains allow statements with wildcard actions or resources. That makes the resulting access difficult to reason about and expands blast radius.
- Recommended mitigation: Replace wildcard actions and resources with narrowly scoped permissions tied to the exact services, APIs, and ARNs required by the workload.
- Evidence:
  - iam actions: ec2:*; iam:*; s3:*
  - iam resources: *
  - policy statements: Allow actions=[ec2:*, s3:*, iam:*] resources=[*]

#### Internet-exposed compute service permits overly broad ingress

- STRIDE category: Spoofing
- Affected resources: `aws_instance.frontend`, `aws_security_group.frontend`
- Trust boundary: `internet-to-service:internet->aws_instance.frontend`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 4 => medium
- Rationale: aws_instance.frontend is reachable from the internet and at least one attached security group allows administrative access or all ports from 0.0.0.0/0. That broad ingress raises the chance of unauthenticated probing and credential attacks.
- Recommended mitigation: Restrict ingress to expected client ports, remove direct administrative exposure, and place management access behind a controlled bastion, VPN, or SSM Session Manager.
- Evidence:
  - security group rules: aws_security_group.frontend ingress tcp 0-65535 from 0.0.0.0/0 (Everything from the internet)
  - public exposure reasons: instance has a public IP path and attached security groups allow internet ingress
  - subnet posture: aws_instance.frontend sits in public subnet aws_subnet.public_web with an internet route

#### Internet-exposed compute service permits overly broad ingress

- STRIDE category: Spoofing
- Affected resources: `aws_instance.admin`, `aws_security_group.admin`
- Trust boundary: `internet-to-service:internet->aws_instance.admin`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +0, lateral_movement +1, blast_radius +1, final_score 4 => medium
- Rationale: aws_instance.admin is reachable from the internet and at least one attached security group allows administrative access or all ports from 0.0.0.0/0. That broad ingress raises the chance of unauthenticated probing and credential attacks.
- Recommended mitigation: Restrict ingress to expected client ports, remove direct administrative exposure, and place management access behind a controlled bastion, VPN, or SSM Session Manager.
- Evidence:
  - security group rules: aws_security_group.admin ingress tcp 3389 from 0.0.0.0/0 (RDP from internet)
  - public exposure reasons: instance has a public IP path and attached security groups allow internet ingress
  - subnet posture: aws_instance.admin sits in public subnet aws_subnet.public_web with an internet route

#### Object storage is publicly accessible

- STRIDE category: Information Disclosure
- Affected resources: `aws_s3_bucket.assets`
- Trust boundary: `internet-to-service:internet->aws_s3_bucket.assets`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 5 => medium
- Rationale: aws_s3_bucket.assets appears to be public through ACLs or bucket policy. Public object access is a common source of unintended data disclosure.
- Recommended mitigation: Remove public ACL or bucket policy access, enable an S3 public access block, and serve content through a controlled CDN or origin access pattern when public distribution is required.
- Evidence:
  - public exposure reasons: bucket ACL `public-read` grants public access; bucket policy allows anonymous access

#### Object storage is publicly accessible

- STRIDE category: Information Disclosure
- Affected resources: `aws_s3_bucket.backups`
- Trust boundary: `internet-to-service:internet->aws_s3_bucket.backups`
- Severity reasoning: internet_exposure +2, privilege_breadth +0, data_sensitivity +2, lateral_movement +0, blast_radius +1, final_score 5 => medium
- Rationale: aws_s3_bucket.backups appears to be public through ACLs or bucket policy. Public object access is a common source of unintended data disclosure.
- Recommended mitigation: Remove public ACL or bucket policy access, enable an S3 public access block, and serve content through a controlled CDN or origin access pattern when public distribution is required.
- Evidence:
  - public exposure reasons: bucket ACL `public-read-write` grants public access

#### Role trust relationship expands blast radius

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.pipeline`
- Trust boundary: `cross-account-or-role-access:arn:aws:iam::444455556666:root->aws_iam_role.pipeline`
- Severity reasoning: internet_exposure +0, privilege_breadth +1, data_sensitivity +0, lateral_movement +2, blast_radius +2, final_score 5 => medium
- Rationale: aws_iam_role.pipeline can be assumed by arn:aws:iam::444455556666:root. Broad or foreign-account trust relationships increase the chance that compromise in one identity domain spills into another.
- Recommended mitigation: Limit trust policies to the exact service principals or roles required, prefer role ARNs over account root where possible, and add conditions such as `ExternalId` or source ARN checks.
- Evidence:
  - trust principals: arn:aws:iam::444455556666:root
  - trust path: trust principal belongs to foreign account 444455556666

### Low

No findings in this severity band.

## Limitations / Unsupported Resources

- AWS support is intentionally limited to a curated v1 resource set rather than the full Terraform AWS provider.
- Subnet public/private classification prefers explicit route table associations and NAT or internet routes when present, but it does not model main-route-table inheritance or every routing edge case.
- IAM analysis resolves inline role policies, customer-managed role-policy attachments, and EC2 instance profiles present in the plan, but it does not expand AWS-managed policy documents that are not materialized in Terraform state.
- Resource-policy analysis focuses on explicit policy documents and Lambda permission resources present in the plan; it does not model every service-specific condition key or every downstream runtime authorization path.
- The engine reasons over Terraform planned values only and does not validate runtime drift, CloudTrail evidence, or post-deploy control-plane activity.

Limits

Unsupported or intentionally scoped areas

  • AWS support is intentionally limited to a curated v1 resource set rather than the full Terraform AWS provider.
  • Subnet public/private classification prefers explicit route table associations and NAT or internet routes when present, but it does not model main-route-table inheritance or every routing edge case.
  • IAM analysis resolves inline role policies, customer-managed role-policy attachments, and EC2 instance profiles present in the plan, but it does not expand AWS-managed policy documents that are not materialized in Terraform state.
  • Resource-policy analysis focuses on explicit policy documents and Lambda permission resources present in the plan; it does not model every service-specific condition key or every downstream runtime authorization path.
  • The engine reasons over Terraform planned values only and does not validate runtime drift, CloudTrail evidence, or post-deploy control-plane activity.