Built-in scenario

sample_aws_lambda_deploy_role_plan.json

Lambda Deploy Role Demo

Analyzed sample_aws_lambda_deploy_role_plan.json with 13 normalized resources and 4 trust boundaries.

Analyze another plan

Active findings

3

Trust boundaries

4

Resources

13

Observations

0
High 0
Medium 3
Low 0

Findings

Severity bands

High

0

No high findings.

Medium

3

Cross-account or broad role trust lacks narrowing conditions

aws-role-trust-missing-narrowing

aws_iam_role.deployer trusts arn:aws:iam::777788889999:role/ci-deployer 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::777788889999:role/ci-deployer->aws_iam_role.deployer
Resources
aws_iam_role.deployer
Evidence
  • trust principals: arn:aws:iam::777788889999:role/ci-deployer
  • trust scope: principal belongs to foreign account 777788889999
  • trust narrowing: supported narrowing conditions present: false; supported narrowing condition keys: none

Role trust relationship expands blast radius

aws-role-trust-expansion

aws_iam_role.deployer can be assumed by arn:aws:iam::777788889999:role/ci-deployer. 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::777788889999:role/ci-deployer->aws_iam_role.deployer
Resources
aws_iam_role.deployer
Evidence
  • trust principals: arn:aws:iam::777788889999:role/ci-deployer
  • trust path: trust principal belongs to foreign account 777788889999

Workload role carries sensitive permissions

aws-workload-role-sensitive-permissions

aws_lambda_function.deployer inherits sensitive privileges from aws_iam_role.deployer, including iam:PassRole. 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.deployer->aws_lambda_function.deployer
Resources
aws_lambda_function.deployer, aws_iam_role.deployer
Evidence
  • iam actions: iam:PassRole
  • policy statements: Allow actions=[lambda:UpdateFunctionCode, lambda:UpdateAlias, iam:PassRole, s3:GetObject] resources=[arn:aws:lambda:us-east-1:333344445555:function:release-deployer, arn:aws:iam::333344445555:role/lambda-runtime-role, arn:aws:s3:::lambda-deploy-artifacts/*]

Low

0

No low findings.

Observations

Controls and mitigating signals

No observations were recorded for this plan.

Trust boundaries

Crossings that drive the model

admin-to-workload-plane

aws_iam_role.deployer -> 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

arn:aws:iam::777788889999:role/ci-deployer -> aws_iam_role.deployer

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

public-subnet-to-private-subnet

aws_subnet.public_edge -> aws_subnet.private_app

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

workload-to-data-store

aws_lambda_function.deployer -> aws_s3_bucket.artifacts

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

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": "Lambda Deploy Role Demo",
  "analyzed_file": "sample_aws_lambda_deploy_role_plan.json",
  "analyzed_path": "/home/fleet/cloud-threat-modeler/fixtures/sample_aws_lambda_deploy_role_plan.json",
  "summary": {
    "normalized_resources": 13,
    "unsupported_resources": 0,
    "trust_boundaries": 4,
    "active_findings": 3,
    "total_findings": 3,
    "suppressed_findings": 0,
    "baselined_findings": 0,
    "severity_counts": {
      "high": 0,
      "medium": 3,
      "low": 0
    }
  },
  "filtering": {
    "total_findings": 3,
    "active_findings": 3,
    "suppressed_findings": 0,
    "baselined_findings": 0,
    "suppressions_path": null,
    "baseline_path": null
  },
  "inventory": {
    "provider": "aws",
    "unsupported_resources": [],
    "metadata": {
      "primary_account_id": "333344445555",
      "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_iam_role.deployer",
        "provider": "aws",
        "resource_type": "aws_iam_role",
        "name": "deployer",
        "category": "iam",
        "identifier": "lambda-deployer-role",
        "arn": "arn:aws:iam::333344445555:role/lambda-deployer-role",
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [
          {
            "effect": "Allow",
            "actions": [
              "lambda:UpdateFunctionCode",
              "lambda:UpdateAlias",
              "iam:PassRole",
              "s3:GetObject"
            ],
            "resources": [
              "arn:aws:lambda:us-east-1:333344445555:function:release-deployer",
              "arn:aws:iam::333344445555:role/lambda-runtime-role",
              "arn:aws:s3:::lambda-deploy-artifacts/*"
            ],
            "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::777788889999:role/ci-deployer"
                }
              }
            ]
          },
          "trust_principals": [
            "arn:aws:iam::777788889999:role/ci-deployer",
            "lambda.amazonaws.com"
          ],
          "trust_statements": [
            {
              "principals": [
                "lambda.amazonaws.com"
              ],
              "narrowing_condition_keys": [],
              "narrowing_conditions": [],
              "has_narrowing_conditions": false
            },
            {
              "principals": [
                "arn:aws:iam::777788889999:role/ci-deployer"
              ],
              "narrowing_condition_keys": [],
              "narrowing_conditions": [],
              "has_narrowing_conditions": false
            }
          ],
          "inline_policy_names": [
            "lambda-deployer-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_internet_gateway.main",
        "provider": "aws",
        "resource_type": "aws_internet_gateway",
        "name": "main",
        "category": "network",
        "identifier": "igw-lambda-001",
        "arn": null,
        "vpc_id": "vpc-lambda-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": "release-deployer",
        "arn": "arn:aws:lambda:us-east-1:333344445555:function:release-deployer",
        "vpc_id": "vpc-lambda-001",
        "subnet_ids": [
          "subnet-lambda-private-app-001"
        ],
        "security_group_ids": [
          "sg-lambda-app-001"
        ],
        "attached_role_arns": [
          "arn:aws:iam::333344445555:role/lambda-deployer-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": false,
          "internet_ingress_capable": false,
          "internet_ingress_reasons": [],
          "public_subnet": false,
          "has_nat_gateway_egress": true,
          "direct_internet_reachable": false
        }
      },
      {
        "address": "aws_nat_gateway.main",
        "provider": "aws",
        "resource_type": "aws_nat_gateway",
        "name": "main",
        "category": "network",
        "identifier": "nat-lambda-001",
        "arn": null,
        "vpc_id": "vpc-lambda-001",
        "subnet_ids": [
          "subnet-lambda-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-lambda-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-lambda-private-001",
        "arn": null,
        "vpc_id": "vpc-lambda-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-lambda-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-lambda-public-001",
        "arn": null,
        "vpc_id": "vpc-lambda-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-lambda-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_app",
        "provider": "aws",
        "resource_type": "aws_route_table_association",
        "name": "private_app",
        "category": "network",
        "identifier": "rtassoc-lambda-private-app-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-lambda-private-001",
          "subnet_id": "subnet-lambda-private-app-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_edge",
        "provider": "aws",
        "resource_type": "aws_route_table_association",
        "name": "public_edge",
        "category": "network",
        "identifier": "rtassoc-lambda-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-lambda-public-001",
          "subnet_id": "subnet-lambda-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.artifacts",
        "provider": "aws",
        "resource_type": "aws_s3_bucket",
        "name": "artifacts",
        "category": "data",
        "identifier": "lambda-deploy-artifacts",
        "arn": "arn:aws:s3:::lambda-deploy-artifacts",
        "vpc_id": null,
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [],
        "policy_statements": [],
        "public_access_configured": false,
        "public_exposure": false,
        "data_sensitivity": "sensitive",
        "metadata": {
          "bucket": "lambda-deploy-artifacts",
          "acl": "private",
          "policy_document": {},
          "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.lambda",
        "provider": "aws",
        "resource_type": "aws_security_group",
        "name": "lambda",
        "category": "network",
        "identifier": "sg-lambda-app-001",
        "arn": null,
        "vpc_id": "vpc-lambda-001",
        "subnet_ids": [],
        "security_group_ids": [],
        "attached_role_arns": [],
        "network_rules": [
          {
            "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": "Private Lambda egress only",
          "group_name": "lambda-app-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_app",
        "provider": "aws",
        "resource_type": "aws_subnet",
        "name": "private_app",
        "category": "network",
        "identifier": "subnet-lambda-private-app-001",
        "arn": null,
        "vpc_id": "vpc-lambda-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.30.2.0/24",
          "availability_zone": "us-east-1a",
          "map_public_ip_on_launch": false,
          "tags": {
            "Tier": "app"
          },
          "is_public_subnet": false,
          "route_table_ids": [
            "rtb-lambda-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_edge",
        "provider": "aws",
        "resource_type": "aws_subnet",
        "name": "public_edge",
        "category": "network",
        "identifier": "subnet-lambda-public-001",
        "arn": null,
        "vpc_id": "vpc-lambda-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.30.1.0/24",
          "availability_zone": "us-east-1a",
          "map_public_ip_on_launch": true,
          "tags": {
            "Tier": "edge"
          },
          "is_public_subnet": true,
          "route_table_ids": [
            "rtb-lambda-public-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-lambda-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.30.0.0/16",
          "tags": {
            "Name": "lambda-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.deployer->aws_lambda_function.deployer",
      "boundary_type": "admin-to-workload-plane",
      "source": "aws_iam_role.deployer",
      "target": "aws_lambda_function.deployer",
      "description": "aws_iam_role.deployer 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:arn:aws:iam::777788889999:role/ci-deployer->aws_iam_role.deployer",
      "boundary_type": "cross-account-or-role-access",
      "source": "arn:aws:iam::777788889999:role/ci-deployer",
      "target": "aws_iam_role.deployer",
      "description": "aws_iam_role.deployer trusts arn:aws:iam::777788889999:role/ci-deployer.",
      "rationale": "A foreign AWS account can cross into this role's trust boundary."
    },
    {
      "identifier": "public-subnet-to-private-subnet:aws_subnet.public_edge->aws_subnet.private_app",
      "boundary_type": "public-subnet-to-private-subnet",
      "source": "aws_subnet.public_edge",
      "target": "aws_subnet.private_app",
      "description": "Traffic can move from aws_subnet.public_edge toward aws_subnet.private_app.",
      "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_lambda_function.deployer->aws_s3_bucket.artifacts",
      "boundary_type": "workload-to-data-store",
      "source": "aws_lambda_function.deployer",
      "target": "aws_s3_bucket.artifacts",
      "description": "aws_lambda_function.deployer can interact with aws_s3_bucket.artifacts.",
      "rationale": "Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:GetObject."
    }
  ],
  "findings": [
    {
      "fingerprint": "sha256:779d6edce767dff9f916fcc604a983e2422f5cbec06afa1ee3628e7c7f333836",
      "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.deployer"
      ],
      "trust_boundary_id": "cross-account-or-role-access:arn:aws:iam::777788889999:role/ci-deployer->aws_iam_role.deployer",
      "rationale": "aws_iam_role.deployer trusts arn:aws:iam::777788889999:role/ci-deployer 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::777788889999:role/ci-deployer"
          ]
        },
        {
          "key": "trust_scope",
          "values": [
            "principal belongs to foreign account 777788889999"
          ]
        },
        {
          "key": "trust_narrowing",
          "values": [
            "supported narrowing conditions present: false",
            "supported narrowing condition keys: none"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 1,
        "data_sensitivity": 0,
        "lateral_movement": 1,
        "blast_radius": 2,
        "final_score": 4,
        "severity": "medium",
        "computed_severity": null
      }
    },
    {
      "fingerprint": "sha256:cb6a7038bd28599e007499cbe69c1732053517b65bebb50ece21368f29197124",
      "title": "Role trust relationship expands blast radius",
      "rule_id": "aws-role-trust-expansion",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_iam_role.deployer"
      ],
      "trust_boundary_id": "cross-account-or-role-access:arn:aws:iam::777788889999:role/ci-deployer->aws_iam_role.deployer",
      "rationale": "aws_iam_role.deployer can be assumed by arn:aws:iam::777788889999:role/ci-deployer. 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::777788889999:role/ci-deployer"
          ]
        },
        {
          "key": "trust_path",
          "values": [
            "trust principal belongs to foreign account 777788889999"
          ]
        }
      ],
      "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
      }
    },
    {
      "fingerprint": "sha256:2c115ec74630511b2ca95853b6925217b80aacdf2b1aeeeb17b5311ee39408d5",
      "title": "Workload role carries sensitive permissions",
      "rule_id": "aws-workload-role-sensitive-permissions",
      "category": "Elevation of Privilege",
      "severity": "medium",
      "affected_resources": [
        "aws_lambda_function.deployer",
        "aws_iam_role.deployer"
      ],
      "trust_boundary_id": "admin-to-workload-plane:aws_iam_role.deployer->aws_lambda_function.deployer",
      "rationale": "aws_lambda_function.deployer inherits sensitive privileges from aws_iam_role.deployer, including iam:PassRole. 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"
          ]
        },
        {
          "key": "policy_statements",
          "values": [
            "Allow actions=[lambda:UpdateFunctionCode, lambda:UpdateAlias, iam:PassRole, s3:GetObject] resources=[arn:aws:lambda:us-east-1:333344445555:function:release-deployer, arn:aws:iam::333344445555:role/lambda-runtime-role, arn:aws:s3:::lambda-deploy-artifacts/*]"
          ]
        }
      ],
      "severity_reasoning": {
        "internet_exposure": 0,
        "privilege_breadth": 1,
        "data_sensitivity": 1,
        "lateral_movement": 1,
        "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
# Lambda Deploy Role Demo

- Analyzed file: `sample_aws_lambda_deploy_role_plan.json`
- Provider: `aws`
- Normalized resources: `13`
- Unsupported resources: `0`

## Summary

This run identified **4 trust boundaries** and **3 findings** across **13 normalized resources**.

- High severity findings: `0`
- Medium severity findings: `3`
- Low severity findings: `0`

## Discovered Trust Boundaries

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

- Source: `aws_subnet.public_edge`
- Target: `aws_subnet.private_app`
- Description: Traffic can move from aws_subnet.public_edge toward aws_subnet.private_app.
- 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_lambda_function.deployer`
- Target: `aws_s3_bucket.artifacts`
- Description: aws_lambda_function.deployer can interact with aws_s3_bucket.artifacts.
- Rationale: Application or function workloads cross into a higher-sensitivity data plane when their attached role allows S3 actions such as s3:GetObject.

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

- Source: `aws_iam_role.deployer`
- Target: `aws_lambda_function.deployer`
- Description: aws_iam_role.deployer 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: `arn:aws:iam::777788889999:role/ci-deployer`
- Target: `aws_iam_role.deployer`
- Description: aws_iam_role.deployer trusts arn:aws:iam::777788889999:role/ci-deployer.
- Rationale: A foreign AWS account can cross into this role's trust boundary.

## Findings

### High

No findings in this severity band.

### Medium

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

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.deployer`
- Trust boundary: `cross-account-or-role-access:arn:aws:iam::777788889999:role/ci-deployer->aws_iam_role.deployer`
- Severity reasoning: internet_exposure +0, privilege_breadth +1, data_sensitivity +0, lateral_movement +1, blast_radius +2, final_score 4 => medium
- Rationale: aws_iam_role.deployer trusts arn:aws:iam::777788889999:role/ci-deployer 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::777788889999:role/ci-deployer
  - trust scope: principal belongs to foreign account 777788889999
  - trust narrowing: supported narrowing conditions present: false; supported narrowing condition keys: none

#### Role trust relationship expands blast radius

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_iam_role.deployer`
- Trust boundary: `cross-account-or-role-access:arn:aws:iam::777788889999:role/ci-deployer->aws_iam_role.deployer`
- 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.deployer can be assumed by arn:aws:iam::777788889999:role/ci-deployer. 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::777788889999:role/ci-deployer
  - trust path: trust principal belongs to foreign account 777788889999

#### Workload role carries sensitive permissions

- STRIDE category: Elevation of Privilege
- Affected resources: `aws_lambda_function.deployer`, `aws_iam_role.deployer`
- Trust boundary: `admin-to-workload-plane:aws_iam_role.deployer->aws_lambda_function.deployer`
- Severity reasoning: internet_exposure +0, privilege_breadth +1, data_sensitivity +1, lateral_movement +1, blast_radius +2, final_score 5 => medium
- Rationale: aws_lambda_function.deployer inherits sensitive privileges from aws_iam_role.deployer, including iam:PassRole. 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
  - policy statements: Allow actions=[lambda:UpdateFunctionCode, lambda:UpdateAlias, iam:PassRole, s3:GetObject] resources=[arn:aws:lambda:us-east-1:333344445555:function:release-deployer, arn:aws:iam::333344445555:role/lambda-runtime-role, arn:aws:s3:::lambda-deploy-artifacts/*]

### 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.