Skip to main content

Ensure EventBridge Event Buses Do Not Allow Unknown Cross-Account Access

Overview

This check verifies that your Amazon EventBridge event buses have resource policies that restrict cross-account access to only known, trusted AWS accounts. EventBridge event buses can receive events from other AWS accounts, but allowing unknown or overly broad access creates security risks.

Risk

If an EventBridge event bus allows unknown cross-account access, malicious actors could:

  • Inject spoofed events that trigger rules and invoke downstream targets
  • Cause unintended actions in your AWS environment through event-driven workflows
  • Expose sensitive data via targets that process the malicious events
  • Enable lateral movement if event rules invoke over-privileged IAM roles
  • Disrupt services or increase costs through event floods

This is a high severity issue because EventBridge often orchestrates critical business workflows.

Remediation Steps

Prerequisites

You need permission to view and modify EventBridge event bus policies. This typically requires the events:DescribeEventBus, events:PutPermission, and events:RemovePermission permissions.

AWS Console Method

  1. Open the Amazon EventBridge console in us-east-1 (or your target region)
  2. In the left navigation, click Event buses
  3. Select the event bus flagged by Prowler
  4. Click the Permissions tab
  5. Review the resource policy - look for:
    • Principals set to * (wildcard) without organizational conditions
    • Unknown or untrusted AWS account IDs
    • Overly broad access patterns
  6. Click Edit to modify the policy
  7. Remove any statements granting access to unknown accounts or wildcards
  8. Click Save

Tip: If you need cross-account access, only allow specific, trusted AWS account IDs or use organizational conditions (see best practices below).

AWS CLI (optional)

View Current Permissions

First, check the current event bus policy:

aws events describe-event-bus \
--name <your-event-bus-name> \
--region us-east-1

For the default event bus, omit the --name parameter:

aws events describe-event-bus --region us-east-1

The output shows the Policy field containing the resource policy JSON. Look for any Statement entries with unknown principals.

Remove Specific Permission

If you identified a statement to remove, use the statement ID:

aws events remove-permission \
--event-bus-name <your-event-bus-name> \
--statement-id <statement-id-to-remove> \
--region us-east-1

Remove All Permissions

To remove all cross-account permissions from an event bus:

aws events remove-permission \
--event-bus-name <your-event-bus-name> \
--remove-all-permissions \
--region us-east-1

Warning: This removes ALL cross-account permissions. Only use this if you want to completely restrict the event bus to same-account access.

Add Trusted Account Permission (if needed)

If you need to allow a specific trusted account:

aws events put-permission \
--event-bus-name <your-event-bus-name> \
--statement-id AllowTrustedAccount \
--action events:PutEvents \
--principal <trusted-account-id> \
--region us-east-1

Allow Organization-Wide Access (secure alternative)

To allow all accounts in your AWS Organization while blocking external accounts:

aws events put-permission \
--event-bus-name <your-event-bus-name> \
--statement-id AllowOrganization \
--action events:PutEvents \
--principal "*" \
--condition '{"Type":"StringEquals","Key":"aws:PrincipalOrgID","Value":"o-xxxxxxxxxx"}' \
--region us-east-1

Replace o-xxxxxxxxxx with your AWS Organization ID.

CloudFormation (optional)

Secure Event Bus with Restricted Access

This template creates an EventBridge event bus with optional cross-account access limited to a specific trusted account:

AWSTemplateFormatVersion: '2010-09-09'
Description: EventBridge event bus with restricted cross-account access

Parameters:
EventBusName:
Type: String
Default: my-event-bus
Description: Name of the EventBridge event bus

TrustedAccountId:
Type: String
Description: AWS Account ID allowed to send events (leave empty for same-account only)
Default: ''

Conditions:
AllowCrossAccount: !Not [!Equals [!Ref TrustedAccountId, '']]

Resources:
EventBus:
Type: AWS::Events::EventBus
Properties:
Name: !Ref EventBusName

EventBusPolicy:
Type: AWS::Events::EventBusPolicy
Condition: AllowCrossAccount
Properties:
EventBusName: !Ref EventBus
StatementId: AllowTrustedAccount
Action: events:PutEvents
Principal: !Ref TrustedAccountId

Deploy the Template

aws cloudformation deploy \
--template-file eventbridge-secure.yaml \
--stack-name secure-eventbridge \
--parameter-overrides \
EventBusName=my-secure-bus \
TrustedAccountId=123456789012 \
--region us-east-1

To create an event bus with no cross-account access, omit the TrustedAccountId parameter.

Terraform (optional)

Secure Event Bus Module

variable "event_bus_name" {
description = "Name of the EventBridge event bus"
type = string
default = "my-event-bus"
}

variable "trusted_account_id" {
description = "AWS Account ID allowed to send events (leave empty for same-account only)"
type = string
default = ""
}

resource "aws_cloudwatch_event_bus" "this" {
name = var.event_bus_name
}

# Only create the policy if a trusted account is specified
resource "aws_cloudwatch_event_bus_policy" "this" {
count = var.trusted_account_id != "" ? 1 : 0
event_bus_name = aws_cloudwatch_event_bus.this.name

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "AllowTrustedAccount"
Effect = "Allow"
Principal = {
AWS = "arn:aws:iam::${var.trusted_account_id}:root"
}
Action = "events:PutEvents"
Resource = aws_cloudwatch_event_bus.this.arn
}
]
})
}

output "event_bus_arn" {
description = "ARN of the EventBridge event bus"
value = aws_cloudwatch_event_bus.this.arn
}

output "event_bus_name" {
description = "Name of the EventBridge event bus"
value = aws_cloudwatch_event_bus.this.name
}

Apply the Configuration

terraform init
terraform apply -var="event_bus_name=my-secure-bus" -var="trusted_account_id=123456789012"

To create an event bus with no cross-account access:

terraform apply -var="event_bus_name=my-secure-bus"

Verification

After making changes, verify the event bus policy is properly restricted:

  1. Return to the EventBridge console and select your event bus
  2. Click the Permissions tab
  3. Confirm only trusted accounts (or no external accounts) are listed
CLI Verification
aws events describe-event-bus \
--name <your-event-bus-name> \
--region us-east-1 \
--query 'Policy' \
--output text | python3 -m json.tool

Review the JSON output and verify:

  • No wildcards (*) in Principal without organizational conditions
  • Only known, trusted account IDs are listed
  • The Action is limited to events:PutEvents

Additional Resources

Notes

  • Default event bus: The default event bus exists in every AWS account and may have accumulated permissions over time. Review it carefully.
  • Partner event buses: Event buses created for SaaS partner integrations have specific permission requirements. Consult the partner documentation before modifying.
  • Event patterns as defense-in-depth: Even with proper bus permissions, configure event rules with specific account field patterns to filter events by source account.
  • Audit regularly: Cross-account permissions can accumulate. Include EventBridge event bus policies in your regular security reviews.
  • Organization-scoped access: Using aws:PrincipalOrgID conditions is more secure than listing individual account IDs, as it automatically includes new accounts in your organization while blocking external accounts.