Skip to content

migrate 8 workshop samples from AgentCore Browser to features tree and audit all browser READMEs#1647

Merged
rajeshkumarravi merged 5 commits into
awslabs:mainfrom
BharathiSrini:ac-browser-samples
Jun 11, 2026
Merged

migrate 8 workshop samples from AgentCore Browser to features tree and audit all browser READMEs#1647
rajeshkumarravi merged 5 commits into
awslabs:mainfrom
BharathiSrini:ac-browser-samples

Conversation

@BharathiSrini

Copy link
Copy Markdown
Collaborator

Amazon Bedrock AgentCore Samples Pull Request

Important

  1. We strictly follow a issue-first approach, please first open an issue relating to this Pull Request.
  2. Once this Pull Request is ready for review please attach review ready label to it. Only PRs with review ready will be reviewed.

Issue number:

Concise description of the PR

Migrates 8 missing Browser feature samples from 06-workshops into 01-features/03-connect-your-agent-to-anything/02-browser,
converts notebooks to standalone Python scripts, fixes a cleanup bug in web-bot-auth,
and audits all 13 Browser sample READMEs against their source notebooks to fill content gaps.

User experience

Before:

  • 8 Browser samples existed only as workshop notebooks under 06-workshops/05-AgentCore-tools/02-Agent-Core-browser-tool/ and were not accessible from the main features tree:
    • Web Bot Auth Signing (RFC 9421 request signing)
    • Public browser from private VPC runtime
    • VPC browser from VPC runtime
    • Browser session profiles (cookie/localStorage persistence)
    • Squid proxy routing with audit logs
    • Browser extensions (S3-hosted zip loading)
    • Chrome enterprise policies and custom root CAs
    • OS-level actions (InvokeBrowser API)
  • web_bot_auth.py cleanup failed with ConflictException because AgentCoreBrowser leaves sessions in "READY" status (not "ACTIVE") and the list API returns sessions under "items" (not
    "browserSessions")
  • READMEs across all 13 Browser samples were missing content present in the source notebooks: architecture diagrams were ASCII blocks floating inside Overview sections rather than under a
    proper ## Architecture heading or using available PNG images; several READMEs were missing important notes (troubleshooting entries, recording review steps, rrweb replay instructions, boto3 SDK
    alternatives, local extension testing, org-applicability guidance)

After:

  • All 8 samples are now available as standalone Python scripts under 01-features/03-connect-your-agent-to-anything/02-browser/06-web-bot-auth through 13-os-actions, each with a full README,
    requirements.txt, and supporting files (CloudFormation templates, YAML configs, helper modules)
  • web_bot_auth.py cleanup correctly lists sessions via sessions.get("items", []), filters by non-terminal status (READY/ACTIVE), stops them, then deletes the browser resource — no more
    ConflictException
  • Architecture diagrams in folders 01–08 use PNG images sourced from the original notebooks where available; 04-strands uses the Mermaid diagram from the notebook; remaining folders retain
    clean ASCII diagrams under a proper ## Architecture section
  • Each README now fully reflects the source notebook: all troubleshooting entries, console walkthrough steps, recording/replay instructions, real-world applicability tables, optional agent
    steps, and SDK alternatives are documented so users have complete context without needing to open the notebook

Checklist

If your change doesn't seem to apply, please leave them unchecked.

  • [x ] I have reviewed the contributing guidelines
  • [ x] Add your name to CONTRIBUTORS.md
  • [ x] Have you checked to ensure there aren't other open Pull Requests for the same update/change?
  • Are you uploading a dataset?
  • [ x] Have you documented Introduction, Architecture Diagram, Prerequisites, Usage, Sample Prompts, and Clean Up steps in your example README?
  • [ x] I agree to resolve any issues created for this example in the future.
  • [ x] I have performed a self-review of this change
  • [ x] Changes have been tested
  • [ x] Changes are documented

Acknowledgment

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Latest scan for commit: fc15a7f | Updated: 2026-06-10 23:10:39 UTC

Security Scan Results

Scan Metadata

  • Project: ASH
  • Scan executed: 2026-06-10T23:10:25+00:00
  • ASH version: 3.0.0

Summary

Scanner Results

The table below shows findings by scanner, with status based on severity thresholds and dependencies:

Column Explanations:

Severity Levels (S/C/H/M/L/I):

  • Suppressed (S): Security findings that have been explicitly suppressed/ignored and don't affect the scanner's pass/fail status
  • Critical (C): The most severe security vulnerabilities requiring immediate remediation (e.g., SQL injection, remote code execution)
  • High (H): Serious security vulnerabilities that should be addressed promptly (e.g., authentication bypasses, privilege escalation)
  • Medium (M): Moderate security risks that should be addressed in normal development cycles (e.g., weak encryption, input validation issues)
  • Low (L): Minor security concerns with limited impact (e.g., information disclosure, weak recommendations)
  • Info (I): Informational findings for awareness with minimal security risk (e.g., code quality suggestions, best practice recommendations)

Other Columns:

  • Time: Duration taken by each scanner to complete its analysis
  • Action: Total number of actionable findings at or above the configured severity threshold that require attention

Scanner Results:

  • PASSED: Scanner found no security issues at or above the configured severity threshold - code is clean for this scanner
  • FAILED: Scanner found security vulnerabilities at or above the threshold that require attention and remediation
  • MISSING: Scanner could not run because required dependencies/tools are not installed or available
  • SKIPPED: Scanner was intentionally disabled or excluded from this scan
  • ERROR: Scanner encountered an execution error and could not complete successfully

Severity Thresholds (Thresh Column):

  • CRITICAL: Only Critical severity findings cause scanner to fail
  • HIGH: High and Critical severity findings cause scanner to fail
  • MEDIUM (MED): Medium, High, and Critical severity findings cause scanner to fail
  • LOW: Low, Medium, High, and Critical severity findings cause scanner to fail
  • ALL: Any finding of any severity level causes scanner to fail

Threshold Source: Values in parentheses indicate where the threshold is configured:

  • (g) = global: Set in the global_settings section of ASH configuration
  • (c) = config: Set in the individual scanner configuration section
  • (s) = scanner: Default threshold built into the scanner itself

Statistics calculation:

  • All statistics are calculated from the final aggregated SARIF report
  • Suppressed findings are counted separately and do not contribute to actionable findings
  • Scanner status is determined by comparing actionable findings to the threshold
Scanner S C H M L I Time Action Result Thresh
bandit 0 0 0 0 8 0 751ms 0 PASSED MED (g)
cdk-nag 0 49 0 2 0 40 10.9s 51 FAILED MED (g)
cfn-nag 0 0 0 0 0 0 3.3s 0 PASSED MED (g)
checkov 17 9 0 0 0 0 10.3s 9 FAILED MED (g)
detect-secr… 0 0 0 0 0 0 1.9s 0 PASSED MED (g)
grype 0 0 0 0 0 0 49.3s 0 PASSED MED (g)
npm-audit 0 0 0 0 0 0 247ms 0 PASSED MED (g)
opengrep 0 0 0 0 0 0 <1ms 0 SKIPPED MED (g)
semgrep 0 0 0 0 0 0 <1ms 0 MISSING MED (g)
syft 0 0 0 0 0 0 4.0s 0 PASSED MED (g)

Detailed Findings

Show 60 actionable findings

Finding 1: CKV_AWS_117

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_117
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/08-vpc-browser-from-vpc/cfn-vpc-browser.yaml:335-464

Description:
Ensure that AWS Lambda function is configured inside a VPC

Code Snippet:

CodeBuildTriggerFunction:
    Type: AWS::Lambda::Function
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W89
            reason: >-
              Lambda custom resource does not require VPC access for CodeBuild triggering; VPC adds latency without benefit here
          - id: W92
            reason: >-
              Reserved concurrency not required for CloudFormation custom resource Lambda in this sample
      checkov:
        skip:
          - id: CKV_AWS_115
            comment: >-
              Reserved concurrency not set for custom resource Lambda; set in production for cost control
          - id: CKV_AWS_116
            comment: >-
              DLQ not required for synchronous CloudFormation custom resource Lambda
    Properties:
      FunctionName: !Sub "${AWS::StackName}-codebuild-trigger"
      Description: "Triggers CodeBuild projects as CloudFormation custom resource"
      Handler: index.handler
      Role: !GetAtt CustomResourceRole.Arn
      Runtime: python3.13
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging
          import time

          logger = logging.getLogger()
          logger.setLevel(logging.INFO)

          def handler(event, context):
              logger.info('Received event: %s', json.dumps(event))
              
              try:
                  if event['RequestType'] == 'Delete':
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                      return
                  
                  project_name = event['ResourceProperties']['ProjectName']
                  wait_for_completion = event['ResourceProperties'].get('WaitForCompletion', 'true').lower() == 'true'
                  
                  logger.info(f"Attempting to start CodeBuild project: {project_name}")
                  logger.info(f"Wait for completion: {wait_for_completion}")
                  
                  # Start the CodeBuild project
                  codebuild = boto3.client('codebuild')
                  
                  # First, verify the project exists
                  try:
                      project_info = codebuild.batch_get_projects(names=[project_name])
                      if not project_info['projects']:
                          raise Exception(f"CodeBuild project '{project_name}' not found")
                      logger.info(f"CodeBuild project '{project_name}' found")
                  except Exception as e:
                      logger.error(f"Error checking project existence: {str(e)}")
                      raise
                  
                  response = codebuild.start_build(projectName=project_name)
                  build_id = response['build']['id']
                  
                  logger.info(f"Successfully started build: {build_id}")
                  
                  if not wait_for_completion:
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                          'BuildId': build_id,
                          'Status': 'STARTED'
                      })
                      return
                  
                  # Wait for the build to complete
                  max_wait_time = context.get_remaining_time_in_millis() / 1000 - 30  # Leave 30s buffer
                  start_time = time.time()
                  
                  while True:
                      if time.time() - start_time > max_wait_time:
                          error_message = f"Build {build_id} timed out"
                          logger.error(error_message)
                          cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_message})
                          return
                      
                      build_response = codebuild.batch_get_builds(ids=[build_id])
                      build_status = build_response['builds'][0]['buildStatus']
                      
                      if build_status == 'SUCCEEDED':
                          logger.info(f"Build {build_id} succeeded")
                          cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                              'BuildId': build_id,
                              'Status': build_status
                          })
                          return
                      elif build_status in ['FAILED', 'FAULT', 'STOPPED', 'TIMED_OUT']:
                          error_message = f"Build {build_id} failed with status: {build_status}"
                          logger.error(error_message)
                          
                          # Get build logs for debugging
                          try:
                              logs_info = build_response['builds'][0].get('logs', {})
                              if logs_info.get('groupName') and logs_info.get('streamName'):
                                  logger.info(f"Build logs available in CloudWatch")
                          except Exception as log_error:
                              logger.warning(f"Could not get log information: {log_error}")
                          
                          cfnresponse.send(event, context, cfnresponse.FAILED, {
                              'Error': error_message,
                              'BuildId': build_id
                          })
                          return
                      
                      logger.info(f"Build {build_id} status: {build_status}")
                      time.sleep(30)  # Check every 30 seconds
                  
              except Exception as e:
                  logger.error('Error: %s', str(e))
                  cfnresponse.send(event, context, cfnresponse.FAILED, {
                      'Error': str(e)
                  })
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-codebuild-trigger"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: Lambda

Finding 2: CKV_AWS_23

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_23
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/08-vpc-browser-from-vpc/cfn-vpc-browser.yaml:1018-1054

Description:
Ensure every security groups rule has a description

Code Snippet:

WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W2
            reason: >-
              Demo web server allows all TCP from VPC CIDR for tutorial simplicity; restrict to specific ports in production
          - id: W5
            reason: >-
              Demo web server allows broad ingress from VPC for tutorial access; restrict in production
          - id: W9
            reason: >-
              Ingress CIDR is VPC range (not /32) for tutorial simplicity; restrict to specific IPs in production
          - id: W27
            reason: >-
              Web server demo accepts wide port range from VPC for tutorial flexibility; restrict to specific ports in production
          - id: W36
            reason: >-
              Egress CIDR not restricted to /32 for demo web server; restrict in production
          - id: W40
            reason: >-
              Web server requires all outbound for updates and responses; restrict in production
    Properties:
      GroupDescription: Security group for web server in private subnet
      VpcId: !Ref ClientVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 0
          ToPort: 65535
          CidrIp: 10.1.0.0/16
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-webserver-sg"

Finding 3: CKV_AWS_24

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_24
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/08-vpc-browser-from-vpc/cfn-vpc-browser.yaml:1246-1298

Description:
Ensure no security groups allow ingress from 0.0.0.0:0 to port 22

Code Snippet:

EC2InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W2
            reason: >-
              Demo EC2 instance allows SSH from 0.0.0.0/0 for tutorial access; restrict to specific IPs in production
          - id: W5
            reason: >-
              Demo EC2 instance allows SSH ingress from internet for tutorial access; restrict in production
          - id: W9
            reason: >-
              SSH CIDR not restricted to /32 for tutorial accessibility; restrict to specific IP in production
    Properties:
      GroupDescription: "Security group for development EC2 instance - allows SSH and outbound HTTPS"
      VpcId: !Ref ClientVPC
      SecurityGroupIngress:
        # SSH Access - For development and troubleshooting
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0 # Note: In production, restrict to specific IP ranges
          Description: "Allow SSH access for development and troubleshooting"
      SecurityGroupEgress:
        # VPC Endpoint Access - For AWS service communication
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          DestinationSecurityGroupId: !Ref VPCEndpointSG
          Description: "Allow outbound HTTPS to VPC endpoints from EC2 Instance"
        # AgentCore Runtime Access - For testing agent invocation
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          DestinationSecurityGroupId: !Ref AgentCoreRuntimeSG
          Description: "Allow outbound HTTPS to AgentCore Runtime from EC2 Instance"
        # Internet Access - For package downloads and updates
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: "Allow HTTPS outbound to internet"
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
          Description: "Allow HTTP outbound to internet"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-ec2-instance-sg"
        - Key: Purpose
          Value: "Development Instance Security"

Finding 4: CKV_AWS_18

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_18
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/08-vpc-browser-from-vpc/cfn-vpc-browser.yaml:1357-1386

Description:
Ensure the S3 bucket has access logging enabled

Code Snippet:

RecordingBucket:
    Type: AWS::S3::Bucket
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W51
            reason: >-
              Sample S3 bucket does not require a bucket policy; access is controlled via IAM roles in this tutorial
          - id: W35
            reason: >-
              Access logging not enabled for this sample bucket; enable in production for audit trails
    Properties:
      BucketName: !Sub "${AWS::StackName}-browser-recording"
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
            BucketKeyEnabled: true
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-browser-recording"
        - Key: StackName
          Value: !Ref AWS::StackName

Finding 5: CKV_AWS_117

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_117
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/07-public-browser-private-vpc/cfn-browser.yaml:327-456

Description:
Ensure that AWS Lambda function is configured inside a VPC

Code Snippet:

CodeBuildTriggerFunction:
    Type: AWS::Lambda::Function
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W89
            reason: >-
              Lambda custom resource does not require VPC access for CodeBuild triggering; VPC adds latency without benefit here
          - id: W92
            reason: >-
              Reserved concurrency not required for CloudFormation custom resource Lambda in this sample
      checkov:
        skip:
          - id: CKV_AWS_115
            comment: >-
              Reserved concurrency not set for custom resource Lambda; set in production for cost control
          - id: CKV_AWS_116
            comment: >-
              DLQ not required for synchronous CloudFormation custom resource Lambda
    Properties:
      FunctionName: !Sub "${AWS::StackName}-codebuild-trigger"
      Description: "Triggers CodeBuild projects as CloudFormation custom resource"
      Handler: index.handler
      Role: !GetAtt CustomResourceRole.Arn
      Runtime: python3.13
      Timeout: 900
      Code:
        ZipFile: |
          import boto3
          import cfnresponse
          import json
          import logging
          import time

          logger = logging.getLogger()
          logger.setLevel(logging.INFO)

          def handler(event, context):
              logger.info('Received event: %s', json.dumps(event))
              
              try:
                  if event['RequestType'] == 'Delete':
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {})
                      return
                  
                  project_name = event['ResourceProperties']['ProjectName']
                  wait_for_completion = event['ResourceProperties'].get('WaitForCompletion', 'true').lower() == 'true'
                  
                  logger.info(f"Attempting to start CodeBuild project: {project_name}")
                  logger.info(f"Wait for completion: {wait_for_completion}")
                  
                  # Start the CodeBuild project
                  codebuild = boto3.client('codebuild')
                  
                  # First, verify the project exists
                  try:
                      project_info = codebuild.batch_get_projects(names=[project_name])
                      if not project_info['projects']:
                          raise Exception(f"CodeBuild project '{project_name}' not found")
                      logger.info(f"CodeBuild project '{project_name}' found")
                  except Exception as e:
                      logger.error(f"Error checking project existence: {str(e)}")
                      raise
                  
                  response = codebuild.start_build(projectName=project_name)
                  build_id = response['build']['id']
                  
                  logger.info(f"Successfully started build: {build_id}")
                  
                  if not wait_for_completion:
                      cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                          'BuildId': build_id,
                          'Status': 'STARTED'
                      })
                      return
                  
                  # Wait for the build to complete
                  max_wait_time = context.get_remaining_time_in_millis() / 1000 - 30  # Leave 30s buffer
                  start_time = time.time()
                  
                  while True:
                      if time.time() - start_time > max_wait_time:
                          error_message = f"Build {build_id} timed out"
                          logger.error(error_message)
                          cfnresponse.send(event, context, cfnresponse.FAILED, {'Error': error_message})
                          return
                      
                      build_response = codebuild.batch_get_builds(ids=[build_id])
                      build_status = build_response['builds'][0]['buildStatus']
                      
                      if build_status == 'SUCCEEDED':
                          logger.info(f"Build {build_id} succeeded")
                          cfnresponse.send(event, context, cfnresponse.SUCCESS, {
                              'BuildId': build_id,
                              'Status': build_status
                          })
                          return
                      elif build_status in ['FAILED', 'FAULT', 'STOPPED', 'TIMED_OUT']:
                          error_message = f"Build {build_id} failed with status: {build_status}"
                          logger.error(error_message)
                          
                          # Get build logs for debugging
                          try:
                              logs_info = build_response['builds'][0].get('logs', {})
                              if logs_info.get('groupName') and logs_info.get('streamName'):
                                  logger.info(f"Build logs available in CloudWatch")
                          except Exception as log_error:
                              logger.warning(f"Could not get log information: {log_error}")
                          
                          cfnresponse.send(event, context, cfnresponse.FAILED, {
                              'Error': error_message,
                              'BuildId': build_id
                          })
                          return
                      
                      logger.info(f"Build {build_id} status: {build_status}")
                      time.sleep(30)  # Check every 30 seconds
                  
              except Exception as e:
                  logger.error('Error: %s', str(e))
                  cfnresponse.send(event, context, cfnresponse.FAILED, {
                      'Error': str(e)
                  })
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-codebuild-trigger"
        - Key: StackName
          Value: !Ref AWS::StackName
        - Key: Module
          Value: Lambda

Finding 6: CKV_AWS_24

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_24
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/07-public-browser-private-vpc/cfn-browser.yaml:1111-1163

Description:
Ensure no security groups allow ingress from 0.0.0.0:0 to port 22

Code Snippet:

EC2InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W2
            reason: >-
              Demo EC2 instance allows SSH from 0.0.0.0/0 for tutorial access; restrict to specific IPs in production
          - id: W5
            reason: >-
              Demo EC2 instance allows SSH ingress from internet for tutorial access; restrict in production
          - id: W9
            reason: >-
              SSH CIDR not restricted to /32 for tutorial accessibility; restrict to specific IP in production
    Properties:
      GroupDescription: "Security group for development EC2 instance - allows SSH and outbound HTTPS"
      VpcId: !Ref ClientVPC
      SecurityGroupIngress:
        # SSH Access - For development and troubleshooting
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0 # Note: In production, restrict to specific IP ranges
          Description: "Allow SSH access for development and troubleshooting"
      SecurityGroupEgress:
        # VPC Endpoint Access - For AWS service communication
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          DestinationSecurityGroupId: !Ref VPCEndpointSG
          Description: "Allow outbound HTTPS to VPC endpoints from EC2 Instance"
        # AgentCore Runtime Access - For testing agent invocation
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          DestinationSecurityGroupId: !Ref AgentCoreRuntimeSG
          Description: "Allow outbound HTTPS to AgentCore Runtime from EC2 Instance"
        # Internet Access - For package downloads and updates
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: "Allow HTTPS outbound to internet"
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
          Description: "Allow HTTP outbound to internet"
      Tags:
        - Key: Name
          Value: !Sub "${AWS::StackName}-ec2-instance-sg"
        - Key: Purpose
          Value: "Development Instance Security"

Finding 7: CKV_AWS_18

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_18
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/10-proxy/agentcore-browser-proxy.yaml:239-267

Description:
Ensure the S3 bucket has access logging enabled

Code Snippet:

LogBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    UpdateReplacePolicy: Retain
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W51
            reason: >-
              Sample S3 log bucket does not require a bucket policy; access is controlled via IAM instance role in this tutorial
          - id: W35
            reason: >-
              Access logging not enabled for this sample log bucket to avoid circular logging; enable in production
    Properties:
      BucketName: !Sub '${AWS::StackName}-squid-logs-${AWS::AccountId}'
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      LifecycleConfiguration:
        Rules:
          - Id: ExpireOldLogs
            Status: Enabled
            ExpirationInDays: 90
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

Finding 8: CKV_AWS_21

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_21
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/10-proxy/agentcore-browser-proxy.yaml:239-267

Description:
Ensure the S3 bucket has versioning enabled

Code Snippet:

LogBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain
    UpdateReplacePolicy: Retain
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W51
            reason: >-
              Sample S3 log bucket does not require a bucket policy; access is controlled via IAM instance role in this tutorial
          - id: W35
            reason: >-
              Access logging not enabled for this sample log bucket to avoid circular logging; enable in production
    Properties:
      BucketName: !Sub '${AWS::StackName}-squid-logs-${AWS::AccountId}'
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      LifecycleConfiguration:
        Rules:
          - Id: ExpireOldLogs
            Status: Enabled
            ExpirationInDays: 90
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

Finding 9: CKV_AWS_149

  • Severity: HIGH
  • Scanner: checkov
  • Rule ID: CKV_AWS_149
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/10-proxy/agentcore-browser-proxy.yaml:273-289

Description:
Ensure that Secrets Manager secret is encrypted using KMS CMK

Code Snippet:

ProxyCredentialsSecret:
    Type: AWS::SecretsManager::Secret
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W77
            reason: >-
              Sample secret uses default AWS-managed key; use a customer-managed KMS key in production
    Properties:
      Name: !Sub '${AWS::StackName}-proxy-credentials'
      Description: Basic auth credentials for the Squid proxy
      GenerateSecretString:
        SecretStringTemplate: '{"username": "proxyuser"}'
        GenerateStringKey: password
        PasswordLength: 24
        ExcludePunctuation: true
        IncludeSpace: false

Finding 10: AwsSolutions-IAM4

  • Severity: HIGH
  • Scanner: cdk-nag
  • Rule ID: AwsSolutions-IAM4
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/07-public-browser-private-vpc/cfn-browser.yaml:96

Description:
The IAM user, role, or group uses AWS managed policies.

Exception Reason: N/A

Code Snippet:

Resources:
  AgentExecutionRole:
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W11
            reason: ECR GetAuthorizationToken, CloudWatch Logs, XRay, and Bedrock inference require wildcard resources; scope
              down in production
          - id: W28
            reason: Explicit role name used for cross-resource reference in this sample; use generated names in production
      checkov:
        skip:
          - comment: Sample IAM role requires broad write access for tutorial demonstration; restrict in production
            id: CKV_AWS_111
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Condition:
              ArnLike:
                aws:SourceArn:
                  Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:*
              StringEquals:
                aws:SourceAccount:
                  Ref: AWS::AccountId
            Effect: Allow
            Principal:
              Service: bedrock-agentcore.amazonaws.com
            Sid: AssumeRolePolicy
        Version: '2012-10-17'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/BedrockAgentCoreFullAccess
      Policies:
        - PolicyDocument:
            Statement:
              - Action:
                  - ecr:BatchGetImage
                  - ecr:GetDownloadUrlForLayer
                  - ecr:BatchCheckLayerAvailability
                Effect: Allow
                Resource:
                  Fn::GetAtt:
                    - ECRRepository
                    - Arn
                Sid: ECRImageAccess
              - Action:
                  - ecr:GetAuthorizationToken
                Effect: Allow
                Resource: '*'
                Sid: ECRTokenAccess
              - Action:
                  - logs:DescribeLogStreams
                  - logs:CreateLogGroup
                  - logs:DescribeLogGroups
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchLogs
              - Action:
                  - xray:PutTraceSegments
                  - xray:PutTelemetryRecords
                  - xray:GetSamplingRules
                  - xray:GetSamplingTargets
                Effect: Allow
                Resource: '*'
                Sid: XRayTracing
              - Action: cloudwatch:PutMetricData
                Condition:
                  StringEquals:
                    cloudwatch:namespace: bedrock-agentcore
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchMetrics
              - Action:
                  - bedrock-agentcore:GetWorkloadAccessToken
                  - bedrock-agentcore:GetWorkloadAccessTokenForJWT
                  - bedrock-agentcore:GetWorkloadAccessTokenForUserId
                Effect: Allow
                Resource:
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default/workload-identity/*
                Sid: GetAgentAccessToken
              - Action:
                  - bedrock:InvokeModel
                  - bedrock:InvokeModelWithResponseStream
                Effect: Allow
                Resource: '*'
                Sid: BedrockModelInvocation
            Version: '2012-10-17'
          PolicyName: AgentCoreExecutionPolicy
      RoleName:
        Fn::Sub: ${AWS::StackName}-${AWS::Region}-agent-execution-role
      Tags:
        - Key: Name
          Value:
            Fn::Sub: ${AWS::StackName}-agent-execution-role
        - Key: StackName
          Value:
            Ref: AWS::StackName
        - Key: Module
          Value: IAM
    Type: AWS::IAM::Role

Finding 11: AwsSolutions-IAM5

  • Severity: HIGH
  • Scanner: cdk-nag
  • Rule ID: AwsSolutions-IAM5
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/07-public-browser-private-vpc/cfn-browser.yaml:96

Description:
The IAM entity contains wildcard permissions and does not have a cdk-nag rule suppression with evidence for those permission.

Exception Reason: N/A

Code Snippet:

Resources:
  AgentExecutionRole:
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W11
            reason: ECR GetAuthorizationToken, CloudWatch Logs, XRay, and Bedrock inference require wildcard resources; scope
              down in production
          - id: W28
            reason: Explicit role name used for cross-resource reference in this sample; use generated names in production
      checkov:
        skip:
          - comment: Sample IAM role requires broad write access for tutorial demonstration; restrict in production
            id: CKV_AWS_111
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Condition:
              ArnLike:
                aws:SourceArn:
                  Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:*
              StringEquals:
                aws:SourceAccount:
                  Ref: AWS::AccountId
            Effect: Allow
            Principal:
              Service: bedrock-agentcore.amazonaws.com
            Sid: AssumeRolePolicy
        Version: '2012-10-17'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/BedrockAgentCoreFullAccess
      Policies:
        - PolicyDocument:
            Statement:
              - Action:
                  - ecr:BatchGetImage
                  - ecr:GetDownloadUrlForLayer
                  - ecr:BatchCheckLayerAvailability
                Effect: Allow
                Resource:
                  Fn::GetAtt:
                    - ECRRepository
                    - Arn
                Sid: ECRImageAccess
              - Action:
                  - ecr:GetAuthorizationToken
                Effect: Allow
                Resource: '*'
                Sid: ECRTokenAccess
              - Action:
                  - logs:DescribeLogStreams
                  - logs:CreateLogGroup
                  - logs:DescribeLogGroups
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchLogs
              - Action:
                  - xray:PutTraceSegments
                  - xray:PutTelemetryRecords
                  - xray:GetSamplingRules
                  - xray:GetSamplingTargets
                Effect: Allow
                Resource: '*'
                Sid: XRayTracing
              - Action: cloudwatch:PutMetricData
                Condition:
                  StringEquals:
                    cloudwatch:namespace: bedrock-agentcore
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchMetrics
              - Action:
                  - bedrock-agentcore:GetWorkloadAccessToken
                  - bedrock-agentcore:GetWorkloadAccessTokenForJWT
                  - bedrock-agentcore:GetWorkloadAccessTokenForUserId
                Effect: Allow
                Resource:
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default/workload-identity/*
                Sid: GetAgentAccessToken
              - Action:
                  - bedrock:InvokeModel
                  - bedrock:InvokeModelWithResponseStream
                Effect: Allow
                Resource: '*'
                Sid: BedrockModelInvocation
            Version: '2012-10-17'
          PolicyName: AgentCoreExecutionPolicy
      RoleName:
        Fn::Sub: ${AWS::StackName}-${AWS::Region}-agent-execution-role
      Tags:
        - Key: Name
          Value:
            Fn::Sub: ${AWS::StackName}-agent-execution-role
        - Key: StackName
          Value:
            Ref: AWS::StackName
        - Key: Module
          Value: IAM
    Type: AWS::IAM::Role

Finding 12: AwsSolutions-IAM5

  • Severity: HIGH
  • Scanner: cdk-nag
  • Rule ID: AwsSolutions-IAM5
  • Location: 01-features/03-connect-your-agent-to-anything/02-browser/07-public-browser-private-vpc/cfn-browser.yaml:96

Description:
The IAM entity contains wildcard permissions and does not have a cdk-nag rule suppression with evidence for those permission.

Exception Reason: N/A

Code Snippet:

Resources:
  AgentExecutionRole:
    Metadata:
      cfn_nag:
        rules_to_suppress:
          - id: W11
            reason: ECR GetAuthorizationToken, CloudWatch Logs, XRay, and Bedrock inference require wildcard resources; scope
              down in production
          - id: W28
            reason: Explicit role name used for cross-resource reference in this sample; use generated names in production
      checkov:
        skip:
          - comment: Sample IAM role requires broad write access for tutorial demonstration; restrict in production
            id: CKV_AWS_111
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Condition:
              ArnLike:
                aws:SourceArn:
                  Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:*
              StringEquals:
                aws:SourceAccount:
                  Ref: AWS::AccountId
            Effect: Allow
            Principal:
              Service: bedrock-agentcore.amazonaws.com
            Sid: AssumeRolePolicy
        Version: '2012-10-17'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/BedrockAgentCoreFullAccess
      Policies:
        - PolicyDocument:
            Statement:
              - Action:
                  - ecr:BatchGetImage
                  - ecr:GetDownloadUrlForLayer
                  - ecr:BatchCheckLayerAvailability
                Effect: Allow
                Resource:
                  Fn::GetAtt:
                    - ECRRepository
                    - Arn
                Sid: ECRImageAccess
              - Action:
                  - ecr:GetAuthorizationToken
                Effect: Allow
                Resource: '*'
                Sid: ECRTokenAccess
              - Action:
                  - logs:DescribeLogStreams
                  - logs:CreateLogGroup
                  - logs:DescribeLogGroups
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchLogs
              - Action:
                  - xray:PutTraceSegments
                  - xray:PutTelemetryRecords
                  - xray:GetSamplingRules
                  - xray:GetSamplingTargets
                Effect: Allow
                Resource: '*'
                Sid: XRayTracing
              - Action: cloudwatch:PutMetricData
                Condition:
                  StringEquals:
                    cloudwatch:namespace: bedrock-agentcore
                Effect: Allow
                Resource: '*'
                Sid: CloudWatchMetrics
              - Action:
                  - bedrock-agentcore:GetWorkloadAccessToken
                  - bedrock-agentcore:GetWorkloadAccessTokenForJWT
                  - bedrock-agentcore:GetWorkloadAccessTokenForUserId
                Effect: Allow
                Resource:
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default
                  - Fn::Sub: arn:aws:bedrock-agentcore:${AWS::Region}:${AWS::AccountId}:workload-identity-directory/default/workload-identity/*
                Sid: GetAgentAccessToken
              - Action:
                  - bedrock:InvokeModel
                  - bedrock:InvokeModelWithResponseStream
                Effect: Allow
                Resource: '*'


<!-- ASH-SECURITY-SCAN-COMMENT -->

Suppress scan findings across 5 files with justification comments:
- cfn-browser.yaml (07): cfn_nag W28/W11/W32/W89/W92; checkov CKV_AWS_136/111/115/116
- cfn-vpc-browser.yaml (08): same set plus W29/W9/W27/W36/W51/W35 for SG and S3
- cloudformation.yaml (09): checkov CKV_AWS_68/86/174; cfn_nag W10/W70 for CloudFront
- agentcore-browser-proxy.yaml (10): cfn_nag W51/W35/W77; pragma comments on IAM action keywords
- chrome_policies.py (12): pragma comment on SECRET_NAME variable (false positive)

All suppressions are sample/demo justifications pointing to production best practices.
@rajeshkumarravi rajeshkumarravi merged commit bc384a8 into awslabs:main Jun 11, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants