aws-samples / aws-samples/sample-FAST-applications
🔒 ASH Security Scan - Monthly Report (2026-09-01)
- Dominant language
- No language data
- Stars
- 32
- Forks
- 13
- Avg merge
- 4h 6m
- Merged PRs (30d)
- 41
Description
# ASH Security Scan - Full Repository Report
**Scan Date:** 2026-09-01T02:26:21+00:00
**Trigger:** schedule
**Type:** Monthly scheduled scan
## Scanner Results Summary
| Scanner | S | C | H | M | L | I | Time | Action | Result | Thresh |
|---------|---|---|---|---|---|---|------|--------|--------|--------|
| bandit | 0 | 9 | 0 | 0 | 201 | 0 | 7.3s | 9 | FAILED | MED (g) |
| cdk-nag | 0 | 0 | 0 | 0 | 0 | 0 | 1m 2s | 0 | PASSED | MED (g) |
| cfn-nag | 0 | 0 | 0 | 0 | 0 | 0 | 40.8s | 0 | PASSED | MED (g) |
| checkov | 0 | 39 | 0 | 0 | 0 | 0 | 31.3s | 39 | FAILED | MED (g) |
| detect-s… | 0 | 18 | 0 | 0 | 0 | 0 | 53.2s | 18 | FAILED | MED (g) |
| grype | 0 | 57 | 0 | 36 | 7 | 0 | 1m 35s | 93 | FAILED | MED (g) |
| npm-audit | 0 | 0 | 0 | 0 | 0 | 0 | 16.9s | 0 | PASSED | MED (g) |
| opengrep | 40 | 64 | 0 | 0 | 0 | 0 | 58.4s | 64 | FAILED | MED (g) |
| semgrep | 0 | 0 | 0 | 0 | 0 | 0 | <1ms | 0 | MISSING | MED (g) |
| syft | 0 | 0 | 0 | 0 | 0 | 0 | 4.4s | 0 | PASSED | MED (g) |
**Status:** ⚠️ Security findings detected
## Detailed Findings
Detailed Findings
Show 223 actionable findings
### Finding 1: B310
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B310
- **Location**: samples/anycompany-bank/backend/api/auth.py:66-68
**Description**:
Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected.
**Code Snippet**:
```
# nosec B310 — the URL is built from our own pool ID, not user input.
with urlopen(url, timeout=5) as response:
import json
```
---
### Finding 2: B310
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B310
- **Location**: samples/anycompany-bank/scripts/deploy_frontend.py:105-107
**Description**:
Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected.
**Code Snippet**:
```
# nosec B310 — the URL is an AWS-issued presigned S3 URL.
with urllib.request.urlopen(request, timeout=300) as response:
if response.status not in (200, 204):
```
---
### Finding 3: B310
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B310
- **Location**: samples/anycompany-bank/scripts/discover_and_invoke_via_oauth.py:121-123
**Description**:
Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected.
**Code Snippet**:
```
try:
with urllib.request.urlopen(request, timeout=120) as resp:
return resp.status, resp.read().decode()
```
---
### Finding 4: B310
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B310
- **Location**: samples/anycompany-bank/scripts/discover_via_oauth_registry.py:79-81
**Description**:
Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected.
**Code Snippet**:
```
try:
with urllib.request.urlopen(request, timeout=60) as resp:
return resp.status, json.loads(resp.read().decode())
```
---
### Finding 5: B104
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B104
- **Location**: samples/aws-specialist-agent/gateway/tools/ltm_mcp_server/server.py:42-44
**Description**:
Possible binding to all interfaces.
**Code Snippet**:
```
mcp = FastMCP("ltm", host="0.0.0.0", stateless_http=True)
```
---
### Finding 6: B104
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B104
- **Location**: samples/aws-specialist-agent/gateway/tools/strands_mcp_server/server.py:35-37
**Description**:
Possible binding to all interfaces.
**Code Snippet**:
```
# AgentCore Runtime MCP contract.
mcp.settings.host = "0.0.0.0"
mcp.settings.port = 8000
```
---
### Finding 7: B104
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B104
- **Location**: samples/aws-specialist-agent/tests/unit/test_ltm_mcp_server.py:140-142
**Description**:
Possible binding to all interfaces.
**Code Snippet**:
```
_load_server_module()
assert captured["fastmcp_kwargs"] == {"host": "0.0.0.0", "stateless_http": True}
```
---
### Finding 8: B104
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B104
- **Location**: samples/aws-specialist-agent/tests/unit/test_strands_mcp_server.py:101-103
**Description**:
Possible binding to all interfaces.
**Code Snippet**:
```
mod = _load_server_module()
assert mod.mcp.settings.host == "0.0.0.0"
assert mod.mcp.settings.port == 8000
```
---
### Finding 9: B310
- **Severity**: HIGH
- **Scanner**: bandit
- **Rule ID**: B310
- **Location**: samples/llm-council/infra-cdk/lambdas/zip-packager/index.py:62-64
**Description**:
Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected.
**Code Snippet**:
```
)
urllib.request.urlopen(req)
```
---
### Finding 10: CKV_AWS_158
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_158
- **Location**: samples/anycompany-bank/infra/console_api.tf:57-60
**Description**:
Ensure that CloudWatch Log Group is encrypted by KMS
**Code Snippet**:
```
resource "aws_cloudwatch_log_group" "console_api" {
name = "/aws/lambda/${var.stack_name}-console-api"
retention_in_days = var.log_retention_days
}
```
---
### Finding 11: CKV_AWS_338
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_338
- **Location**: samples/anycompany-bank/infra/console_api.tf:57-60
**Description**:
Ensure CloudWatch log groups retains logs for at least 1 year
**Code Snippet**:
```
resource "aws_cloudwatch_log_group" "console_api" {
name = "/aws/lambda/${var.stack_name}-console-api"
retention_in_days = var.log_retention_days
}
```
---
### Finding 12: CKV_AWS_173
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_173
- **Location**: samples/anycompany-bank/infra/console_api.tf:149-200
**Description**:
Check encryption settings for Lambda environmental variable
**Code Snippet**:
```
resource "aws_lambda_function" "console_api" {
function_name = "${var.stack_name}-console-api"
role = aws_iam_role.console_api.arn
package_type = "Image"
image_uri = module.console_api_image.image_uri
architectures = ["arm64"]
# Must exceed the longest assessment; the Runtime call itself is capped at
# 600s by the boto3 read timeout in main.py.
timeout = 300
memory_size = 1024
environment {
variables = {
RUNTIME_ARN = aws_bedrockagentcore_agent_runtime.kyc.agent_runtime_arn
REGISTRY_ID = aws_bedrockagentcore_registry.fsi.registry_id
GATEWAY_ID = aws_bedrockagentcore_gateway.kyc.gateway_id
GATEWAY_URL = aws_bedrockagentcore_gateway.kyc.gateway_url
MEMORY_ID = aws_bedrockagentcore_memory.kyc.id
KYC_TOOLS_LAMBDA = aws_lambda_function.kyc_tools.function_name
USER_POOL_ID = aws_cognito_user_pool.console.id
USER_POOL_CLIENT_ID = aws_cognito_user_pool_client.console.id
CONSOLE_ORIGIN = "https://${aws_amplify_branch.console.branch_name}.${aws_amplify_app.console.id}.amplifyapp.com"
# Model-plane facts, mirrored from the runtime's own environment so
# /api/config can report which route and guardrail the deployment is
# configured for. The console API does not invoke models itself; these
# are descriptive only, which is why the same values are set in two
# places rather than read back from the runtime at request time.
INFERENCE_ROUTE = var.inference_route
GUARDRAIL_ID = aws_bedrock_guardrail.kyc.guardrail_id
GUARDRAIL_VERSION = aws_bedrock_guardrail_version.kyc.version
POLICY_ENGINE_ID = aws_bedrockagentcore_policy_engine.kyc.policy_engine_id
POLICY_MODE = var.policy_engine_mode
# AgentCore Harness — the managed agent loop, when deployed. one(...)
# yields null (→ empty env var) when enable_harness = false.
HARNESS_ID = one(aws_bedrockagentcore_harness.kyc[*].harness_id)
}
}
# No replace_triggered_by: the image is content-addressed, so image_uri
# changes on a code edit and Terraform issues an in-place
# update-function-code. Replacing the function instead would tear down the
# Function URL (whose hostname is regenerated) and its resource policy — the
# exact churn that broke the deployed frontend during the refactor.
depends_on = [
aws_iam_role_policy.console_api,
aws_cloudwatch_log_group.console_api,
module.console_api_image,
]
}
```
---
### Finding 13: CKV_AWS_116
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_116
- **Location**: samples/anycompany-bank/infra/console_api.tf:149-200
**Description**:
Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ)
**Code Snippet**:
```
resource "aws_lambda_function" "console_api" {
function_name = "${var.stack_name}-console-api"
role = aws_iam_role.console_api.arn
package_type = "Image"
image_uri = module.console_api_image.image_uri
architectures = ["arm64"]
# Must exceed the longest assessment; the Runtime call itself is capped at
# 600s by the boto3 read timeout in main.py.
timeout = 300
memory_size = 1024
environment {
variables = {
RUNTIME_ARN = aws_bedrockagentcore_agent_runtime.kyc.agent_runtime_arn
REGISTRY_ID = aws_bedrockagentcore_registry.fsi.registry_id
GATEWAY_ID = aws_bedrockagentcore_gateway.kyc.gateway_id
GATEWAY_URL = aws_bedrockagentcore_gateway.kyc.gateway_url
MEMORY_ID = aws_bedrockagentcore_memory.kyc.id
KYC_TOOLS_LAMBDA = aws_lambda_function.kyc_tools.function_name
USER_POOL_ID = aws_cognito_user_pool.console.id
USER_POOL_CLIENT_ID = aws_cognito_user_pool_client.console.id
CONSOLE_ORIGIN = "https://${aws_amplify_branch.console.branch_name}.${aws_amplify_app.console.id}.amplifyapp.com"
# Model-plane facts, mirrored from the runtime's own environment so
# /api/config can report which route and guardrail the deployment is
# configured for. The console API does not invoke models itself; these
# are descriptive only, which is why the same values are set in two
# places rather than read back from the runtime at request time.
INFERENCE_ROUTE = var.inference_route
GUARDRAIL_ID = aws_bedrock_guardrail.kyc.guardrail_id
GUARDRAIL_VERSION = aws_bedrock_guardrail_version.kyc.version
POLICY_ENGINE_ID = aws_bedrockagentcore_policy_engine.kyc.policy_engine_id
POLICY_MODE = var.policy_engine_mode
# AgentCore Harness — the managed agent loop, when deployed. one(...)
# yields null (→ empty env var) when enable_harness = false.
HARNESS_ID = one(aws_bedrockagentcore_harness.kyc[*].harness_id)
}
}
# No replace_triggered_by: the image is content-addressed, so image_uri
# changes on a code edit and Terraform issues an in-place
# update-function-code. Replacing the function instead would tear down the
# Function URL (whose hostname is regenerated) and its resource policy — the
# exact churn that broke the deployed frontend during the refactor.
depends_on = [
aws_iam_role_policy.console_api,
aws_cloudwatch_log_group.console_api,
module.console_api_image,
]
}
```
---
### Finding 14: CKV_AWS_272
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_272
- **Location**: samples/anycompany-bank/infra/console_api.tf:149-200
**Description**:
Ensure AWS Lambda function is configured to validate code-signing
**Code Snippet**:
```
resource "aws_lambda_function" "console_api" {
function_name = "${var.stack_name}-console-api"
role = aws_iam_role.console_api.arn
package_type = "Image"
image_uri = module.console_api_image.image_uri
architectures = ["arm64"]
# Must exceed the longest assessment; the Runtime call itself is capped at
# 600s by the boto3 read timeout in main.py.
timeout = 300
memory_size = 1024
environment {
variables = {
RUNTIME_ARN = aws_bedrockagentcore_agent_runtime.kyc.agent_runtime_arn
REGISTRY_ID = aws_bedrockagentcore_registry.fsi.registry_id
GATEWAY_ID = aws_bedrockagentcore_gateway.kyc.gateway_id
GATEWAY_URL = aws_bedrockagentcore_gateway.kyc.gateway_url
MEMORY_ID = aws_bedrockagentcore_memory.kyc.id
KYC_TOOLS_LAMBDA = aws_lambda_function.kyc_tools.function_name
USER_POOL_ID = aws_cognito_user_pool.console.id
USER_POOL_CLIENT_ID = aws_cognito_user_pool_client.console.id
CONSOLE_ORIGIN = "https://${aws_amplify_branch.console.branch_name}.${aws_amplify_app.console.id}.amplifyapp.com"
# Model-plane facts, mirrored from the runtime's own environment so
# /api/config can report which route and guardrail the deployment is
# configured for. The console API does not invoke models itself; these
# are descriptive only, which is why the same values are set in two
# places rather than read back from the runtime at request time.
INFERENCE_ROUTE = var.inference_route
GUARDRAIL_ID = aws_bedrock_guardrail.kyc.guardrail_id
GUARDRAIL_VERSION = aws_bedrock_guardrail_version.kyc.version
POLICY_ENGINE_ID = aws_bedrockagentcore_policy_engine.kyc.policy_engine_id
POLICY_MODE = var.policy_engine_mode
# AgentCore Harness — the managed agent loop, when deployed. one(...)
# yields null (→ empty env var) when enable_harness = false.
HARNESS_ID = one(aws_bedrockagentcore_harness.kyc[*].harness_id)
}
}
# No replace_triggered_by: the image is content-addressed, so image_uri
# changes on a code edit and Terraform issues an in-place
# update-function-code. Replacing the function instead would tear down the
# Function URL (whose hostname is regenerated) and its resource policy — the
# exact churn that broke the deployed frontend during the refactor.
depends_on = [
aws_iam_role_policy.console_api,
aws_cloudwatch_log_group.console_api,
module.console_api_image,
]
}
```
---
### Finding 15: CKV_AWS_115
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_115
- **Location**: samples/anycompany-bank/infra/console_api.tf:149-200
**Description**:
Ensure that AWS Lambda function is configured for function-level concurrent execution limit
**Code Snippet**:
```
resource "aws_lambda_function" "console_api" {
function_name = "${var.stack_name}-console-api"
role = aws_iam_role.console_api.arn
package_type = "Image"
image_uri = module.console_api_image.image_uri
architectures = ["arm64"]
# Must exceed the longest assessment; the Runtime call itself is capped at
# 600s by the boto3 read timeout in main.py.
timeout = 300
memory_size = 1024
environment {
variables = {
RUNTIME_ARN = aws_bedrockagentcore_agent_runtime.kyc.agent_runtime_arn
REGISTRY_ID = aws_bedrockagentcore_registry.fsi.registry_id
GATEWAY_ID = aws_bedrockagentcore_gateway.kyc.gateway_id
GATEWAY_URL = aws_bedrockagentcore_gateway.kyc.gateway_url
MEMORY_ID = aws_bedrockagentcore_memory.kyc.id
KYC_TOOLS_LAMBDA = aws_lambda_function.kyc_tools.function_name
USER_POOL_ID = aws_cognito_user_pool.console.id
USER_POOL_CLIENT_ID = aws_cognito_user_pool_client.console.id
CONSOLE_ORIGIN = "https://${aws_amplify_branch.console.branch_name}.${aws_amplify_app.console.id}.amplifyapp.com"
# Model-plane facts, mirrored from the runtime's own environment so
# /api/config can report which route and guardrail the deployment is
# configured for. The console API does not invoke models itself; these
# are descriptive only, which is why the same values are set in two
# places rather than read back from the runtime at request time.
INFERENCE_ROUTE = var.inference_route
GUARDRAIL_ID = aws_bedrock_guardrail.kyc.guardrail_id
GUARDRAIL_VERSION = aws_bedrock_guardrail_version.kyc.version
POLICY_ENGINE_ID = aws_bedrockagentcore_policy_engine.kyc.policy_engine_id
POLICY_MODE = var.policy_engine_mode
# AgentCore Harness — the managed agent loop, when deployed. one(...)
# yields null (→ empty env var) when enable_harness = false.
HARNESS_ID = one(aws_bedrockagentcore_harness.kyc[*].harness_id)
}
}
# No replace_triggered_by: the image is content-addressed, so image_uri
# changes on a code edit and Terraform issues an in-place
# update-function-code. Replacing the function instead would tear down the
# Function URL (whose hostname is regenerated) and its resource policy — the
# exact churn that broke the deployed frontend during the refactor.
depends_on = [
aws_iam_role_policy.console_api,
aws_cloudwatch_log_group.console_api,
module.console_api_image,
]
}
```
---
### Finding 16: CKV_AWS_117
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_117
- **Location**: samples/anycompany-bank/infra/console_api.tf:149-200
**Description**:
Ensure that AWS Lambda function is configured inside a VPC
**Code Snippet**:
```
resource "aws_lambda_function" "console_api" {
function_name = "${var.stack_name}-console-api"
role = aws_iam_role.console_api.arn
package_type = "Image"
image_uri = module.console_api_image.image_uri
architectures = ["arm64"]
# Must exceed the longest assessment; the Runtime call itself is capped at
# 600s by the boto3 read timeout in main.py.
timeout = 300
memory_size = 1024
environment {
variables = {
RUNTIME_ARN = aws_bedrockagentcore_agent_runtime.kyc.agent_runtime_arn
REGISTRY_ID = aws_bedrockagentcore_registry.fsi.registry_id
GATEWAY_ID = aws_bedrockagentcore_gateway.kyc.gateway_id
GATEWAY_URL = aws_bedrockagentcore_gateway.kyc.gateway_url
MEMORY_ID = aws_bedrockagentcore_memory.kyc.id
KYC_TOOLS_LAMBDA = aws_lambda_function.kyc_tools.function_name
USER_POOL_ID = aws_cognito_user_pool.console.id
USER_POOL_CLIENT_ID = aws_cognito_user_pool_client.console.id
CONSOLE_ORIGIN = "https://${aws_amplify_branch.console.branch_name}.${aws_amplify_app.console.id}.amplifyapp.com"
# Model-plane facts, mirrored from the runtime's own environment so
# /api/config can report which route and guardrail the deployment is
# configured for. The console API does not invoke models itself; these
# are descriptive only, which is why the same values are set in two
# places rather than read back from the runtime at request time.
INFERENCE_ROUTE = var.inference_route
GUARDRAIL_ID = aws_bedrock_guardrail.kyc.guardrail_id
GUARDRAIL_VERSION = aws_bedrock_guardrail_version.kyc.version
POLICY_ENGINE_ID = aws_bedrockagentcore_policy_engine.kyc.policy_engine_id
POLICY_MODE = var.policy_engine_mode
# AgentCore Harness — the managed agent loop, when deployed. one(...)
# yields null (→ empty env var) when enable_harness = false.
HARNESS_ID = one(aws_bedrockagentcore_harness.kyc[*].harness_id)
}
}
# No replace_triggered_by: the image is content-addressed, so image_uri
# changes on a code edit and Terraform issues an in-place
# update-function-code. Replacing the function instead would tear down the
# Function URL (whose hostname is regenerated) and its resource policy — the
# exact churn that broke the deployed frontend during the refactor.
depends_on = [
aws_iam_role_policy.console_api,
aws_cloudwatch_log_group.console_api,
module.console_api_image,
]
}
```
---
### Finding 17: CKV_AWS_50
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_50
- **Location**: samples/anycompany-bank/infra/console_api.tf:149-200
**Description**:
X-Ray tracing is enabled for Lambda
**Code Snippet**:
```
resource "aws_lambda_function" "console_api" {
function_name = "${var.stack_name}-console-api"
role = aws_iam_role.console_api.arn
package_type = "Image"
image_uri = module.console_api_image.image_uri
architectures = ["arm64"]
# Must exceed the longest assessment; the Runtime call itself is capped at
# 600s by the boto3 read timeout in main.py.
timeout = 300
memory_size = 1024
environment {
variables = {
RUNTIME_ARN = aws_bedrockagentcore_agent_runtime.kyc.agent_runtime_arn
REGISTRY_ID = aws_bedrockagentcore_registry.fsi.registry_id
GATEWAY_ID = aws_bedrockagentcore_gateway.kyc.gateway_id
GATEWAY_URL = aws_bedrockagentcore_gateway.kyc.gateway_url
MEMORY_ID = aws_bedrockagentcore_memory.kyc.id
KYC_TOOLS_LAMBDA = aws_lambda_function.kyc_tools.function_name
USER_POOL_ID = aws_cognito_user_pool.console.id
USER_POOL_CLIENT_ID = aws_cognito_user_pool_client.console.id
CONSOLE_ORIGIN = "https://${aws_amplify_branch.console.branch_name}.${aws_amplify_app.console.id}.amplifyapp.com"
# Model-plane facts, mirrored from the runtime's own environment so
# /api/config can report which route and guardrail the deployment is
# configured for. The console API does not invoke models itself; these
# are descriptive only, which is why the same values are set in two
# places rather than read back from the runtime at request time.
INFERENCE_ROUTE = var.inference_route
GUARDRAIL_ID = aws_bedrock_guardrail.kyc.guardrail_id
GUARDRAIL_VERSION = aws_bedrock_guardrail_version.kyc.version
POLICY_ENGINE_ID = aws_bedrockagentcore_policy_engine.kyc.policy_engine_id
POLICY_MODE = var.policy_engine_mode
# AgentCore Harness — the managed agent loop, when deployed. one(...)
# yields null (→ empty env var) when enable_harness = false.
HARNESS_ID = one(aws_bedrockagentcore_harness.kyc[*].harness_id)
}
}
# No replace_triggered_by: the image is content-addressed, so image_uri
# changes on a code edit and Terraform issues an in-place
# update-function-code. Replacing the function instead would tear down the
# Function URL (whose hostname is regenerated) and its resource policy — the
# exact churn that broke the deployed frontend during the refactor.
depends_on = [
aws_iam_role_policy.console_api,
aws_cloudwatch_log_group.console_api,
module.console_api_image,
]
}
```
---
### Finding 18: CKV_AWS_158
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_158
- **Location**: samples/anycompany-bank/infra/gateway.tf:16-19
**Description**:
Ensure that CloudWatch Log Group is encrypted by KMS
**Code Snippet**:
```
resource "aws_cloudwatch_log_group" "kyc_tools" {
name = "/aws/lambda/${var.stack_name}-kyc-tools"
retention_in_days = var.log_retention_days
}
```
---
### Finding 19: CKV_AWS_338
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_338
- **Location**: samples/anycompany-bank/infra/gateway.tf:16-19
**Description**:
Ensure CloudWatch log groups retains logs for at least 1 year
**Code Snippet**:
```
resource "aws_cloudwatch_log_group" "kyc_tools" {
name = "/aws/lambda/${var.stack_name}-kyc-tools"
retention_in_days = var.log_retention_days
}
```
---
### Finding 20: CKV_AWS_116
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_116
- **Location**: samples/anycompany-bank/infra/gateway.tf:75-91
**Description**:
Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ)
**Code Snippet**:
```
resource "aws_lambda_function" "kyc_tools" {
function_name = "${var.stack_name}-kyc-tools"
role = aws_iam_role.kyc_tools_lambda.arn
handler = "kyc_tools_lambda.handler"
runtime = "python3.13"
architectures = ["arm64"]
timeout = 30
memory_size = 256
filename = data.archive_file.kyc_tools.output_path
source_code_hash = data.archive_file.kyc_tools.output_base64sha256
depends_on = [
aws_cloudwatch_log_group.kyc_tools,
aws_iam_role_policy.kyc_tools_lambda,
]
}
```
---
### Finding 21: CKV_AWS_272
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_272
- **Location**: samples/anycompany-bank/infra/gateway.tf:75-91
**Description**:
Ensure AWS Lambda function is configured to validate code-signing
**Code Snippet**:
```
resource "aws_lambda_function" "kyc_tools" {
function_name = "${var.stack_name}-kyc-tools"
role = aws_iam_role.kyc_tools_lambda.arn
handler = "kyc_tools_lambda.handler"
runtime = "python3.13"
architectures = ["arm64"]
timeout = 30
memory_size = 256
filename = data.archive_file.kyc_tools.output_path
source_code_hash = data.archive_file.kyc_tools.output_base64sha256
depends_on = [
aws_cloudwatch_log_group.kyc_tools,
aws_iam_role_policy.kyc_tools_lambda,
]
}
```
---
### Finding 22: CKV_AWS_115
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_115
- **Location**: samples/anycompany-bank/infra/gateway.tf:75-91
**Description**:
Ensure that AWS Lambda function is configured for function-level concurrent execution limit
**Code Snippet**:
```
resource "aws_lambda_function" "kyc_tools" {
function_name = "${var.stack_name}-kyc-tools"
role = aws_iam_role.kyc_tools_lambda.arn
handler = "kyc_tools_lambda.handler"
runtime = "python3.13"
architectures = ["arm64"]
timeout = 30
memory_size = 256
filename = data.archive_file.kyc_tools.output_path
source_code_hash = data.archive_file.kyc_tools.output_base64sha256
depends_on = [
aws_cloudwatch_log_group.kyc_tools,
aws_iam_role_policy.kyc_tools_lambda,
]
}
```
---
### Finding 23: CKV_AWS_117
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_117
- **Location**: samples/anycompany-bank/infra/gateway.tf:75-91
**Description**:
Ensure that AWS Lambda function is configured inside a VPC
**Code Snippet**:
```
resource "aws_lambda_function" "kyc_tools" {
function_name = "${var.stack_name}-kyc-tools"
role = aws_iam_role.kyc_tools_lambda.arn
handler = "kyc_tools_lambda.handler"
runtime = "python3.13"
architectures = ["arm64"]
timeout = 30
memory_size = 256
filename = data.archive_file.kyc_tools.output_path
source_code_hash = data.archive_file.kyc_tools.output_base64sha256
depends_on = [
aws_cloudwatch_log_group.kyc_tools,
aws_iam_role_policy.kyc_tools_lambda,
]
}
```
---
### Finding 24: CKV_AWS_50
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_50
- **Location**: samples/anycompany-bank/infra/gateway.tf:75-91
**Description**:
X-Ray tracing is enabled for Lambda
**Code Snippet**:
```
resource "aws_lambda_function" "kyc_tools" {
function_name = "${var.stack_name}-kyc-tools"
role = aws_iam_role.kyc_tools_lambda.arn
handler = "kyc_tools_lambda.handler"
runtime = "python3.13"
architectures = ["arm64"]
timeout = 30
memory_size = 256
filename = data.archive_file.kyc_tools.output_path
source_code_hash = data.archive_file.kyc_tools.output_base64sha256
depends_on = [
aws_cloudwatch_log_group.kyc_tools,
aws_iam_role_policy.kyc_tools_lambda,
]
}
```
---
### Finding 25: CKV_AWS_107
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_107
- **Location**: samples/anycompany-bank/infra/harness.tf:123-260
**Description**:
Ensure IAM policies does not allow credentials exposure
**Code Snippet**:
```
data "aws_iam_policy_document" "harness" {
count = var.enable_harness ? 1 : 0
# Model invocation — the harness calls Bedrock for the agent loop.
statement {
sid = "BedrockModelInvocation"
effect = "Allow"
actions = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
]
resources = [
"arn:aws:bedrock:*::foundation-model/*",
"arn:aws:bedrock:${local.region}:${local.account_id}:inference-profile/*",
]
}
# The managed harness image is pulled from ECR Public on the public network.
statement {
sid = "EcrPublicTokenAccess"
effect = "Allow"
actions = ["ecr-public:GetAuthorizationToken"]
resources = ["*"]
}
statement {
sid = "StsForEcrPublicPull"
effect = "Allow"
actions = ["sts:GetServiceBearerToken"]
resources = ["*"]
}
# Observability — traces to X-Ray, logs and metrics to CloudWatch. Same shape
# as the Runtime role so both agents land in the unified trace view.
statement {
sid = "Observability"
effect = "Allow"
actions = [
"xray:PutTraceSegments",
"xray:PutTelemetryRecords",
"xray:GetSamplingRules",
"xray:GetSamplingTargets",
]
resources = ["*"]
}
statement {
sid = "CloudWatchLogs"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogStreams",
]
resources = ["arn:aws:logs:${local.region}:${local.account_id}:log-group:/aws/bedrock-agentcore/runtimes/*"]
}
statement {
sid = "CloudWatchLogsDescribeGroups"
effect = "Allow"
actions = ["logs:DescribeLogGroups"]
resources = ["arn:aws:logs:${local.region}:${local.account_id}:log-group:*"]
}
statement {
sid = "CloudWatchLogsResourcePolicy"
effect = "Allow"
actions = ["logs:PutResourcePolicy"]
resources = ["*"]
}
statement {
sid = "CloudWatchMetrics"
effect = "Allow"
actions = ["cloudwatch:PutMetricData"]
resources = ["*"]
condition {
test = "StringEquals"
variable = "cloudwatch:namespace"
values = ["bedrock-agentcore"]
}
}
# Workload identity for the managed loop.
statement {
sid = "WorkloadIdentity"
effect = "Allow"
actions = [
"bedrock-agentcore:GetWorkloadAccessToken",
"bedrock-agentcore:GetWorkloadAccessTokenForJWT",
]
resources = [
"arn:aws:bedrock-agentcore:${local.region}:${local.account_id}:workload-identity-directory/default",
"arn:aws:bedrock-agentcore:${local.region}:${local.account_id}:workload-identity-directory/default/workload-identity/*",
]
}
# This harness's wiring: reach the shared Gateway (its KYC tools) under the
# same ARN the Runtime role grants.
statement {
sid = "InvokeGateway"
effect = "Allow"
actions = ["bedrock-agentcore:InvokeGateway"]
resources = [aws_bedrockagentcore_gateway.kyc.gateway_arn]
}
# Fetch the S3 skill bundle at session start. The docs require both GetObject
# (read the SKILL.md) and ListBucket (enumerate the skill prefix).
statement {
sid = "SkillBucketRead"
effect = "Allow"
actions = ["s3:GetObject"]
resources = ["${aws_s3_bucket.harness_skills[0].arn}/*"]
}
statement {
sid = "SkillBucketList"
effect = "Allow"
actions = ["s3:ListBucket"]
resources = [aws_s3_bucket.harness_skills[0].arn]
}
# The harness provisions its OWN managed short/long-term memory (the
# managedMemoryConfiguration the service creates by default) — a resource
# distinct from the Runtime's shared KYC memory, and named after the harness
# (`-`). Its id is not known at plan time,
# so scope to the harness-name prefix. Without this the loop fails mid-run on
# `ListEvents` against that managed memory.
statement {
sid = "ManagedMemoryAccess"
effect = "Allow"
actions = [
"bedrock-agentcore:CreateEvent",
"bedrock-agentcore:GetEvent",
"bedrock-agentcore:ListEvents",
"bedrock-agentcore:ListSessions",
"bedrock-agentcore:RetrieveMemoryRecords",
"bedrock-agentcore:ListMemoryRecords",
]
resources = [
"arn:aws:bedrock-agentcore:${local.region}:${local.account_id}:memory/${local.harness_name}-*",
]
}
}
```
---
### Finding 26: CKV_AWS_136
- **Severity**: HIGH
- **Scanner**: checkov
- **Rule ID**: CKV_AWS_136
- **Location**: samples/anycompany-bank/infra/modules/ecr-image/main.tf:30-43
**Description**:
Ensure that ECR repositories are encrypted using KMS
**Code Snippet**:
```
resource "aws_ecr_repository" "this" {
name = var.repository_name
image_tag_mutability = "MUTABLE"
# Demo stack: allow `terraform destroy` to remove the repo with images in it.
force_delete = true
image_scanning_configuration {
scan_on_push = true
}
---
*This issue was automatically created by the monthly security scan workflow.*
Contributor guide
Research direction
Start with the listed findings in samples/anycompany-bank and samples/aws-specialist-agent, especially the referenced Python and Terraform files, and review the ASH scan output by rule and location. Done means the actionable findings are addressed or explicitly accepted with rationale and a subsequent scheduled scan no longer reports unresolved blockers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, python, terraform
- Domain
- cloud, infrastructure, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 15/100