Active findings
16Built-in scenario
sample_aws_nightmare_plan.jsonNightmare Plan Demo
Analyzed sample_aws_nightmare_plan.json with 25 normalized resources and 19 trust boundaries.
Trust boundaries
19Resources
25Observations
0Findings
Severity bands
High
5Database is reachable from overly permissive sources
aws-database-permissive-ingressaws_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-segmentationaws_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-expansionaws_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-permissionsaws_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-permissionsaws_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
11Cross-account or broad role trust lacks narrowing conditions
aws-role-trust-missing-narrowingaws_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-narrowingaws_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-disabledaws_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-permissionsaws_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-permissionsaws_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-permissionsaws_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-ingressaws_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-ingressaws_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-accessaws_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-accessaws_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-expansionaws_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
0No 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.