Active findings
3Built-in scenario
sample_aws_lambda_deploy_role_plan.jsonLambda Deploy Role Demo
Analyzed sample_aws_lambda_deploy_role_plan.json with 13 normalized resources and 4 trust boundaries.
Trust boundaries
4Resources
13Observations
0Findings
Severity bands
High
0No high findings.
Medium
3Cross-account or broad role trust lacks narrowing conditions
aws-role-trust-missing-narrowingaws_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-expansionaws_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-permissionsaws_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
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.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.