Back to Checks
SQS queue policy does not allow public access
sqs_queues_not_publicly_accessible
Service: sqsSeverity: critical
OfficialBuilt-inVerified
Categories:internet-exposed
Resource Type:AwsSqsQueue
Amazon SQS queue policies are assessed for public access. The finding highlights queues with Allow statements using a wildcard Principal without restrictive conditions, compared to queues that only grant access to the owning account or explicitly trusted principals.
Risk
Public SQS access can expose message data (confidentiality), enable unauthorized send/receive or tampering (integrity), and allow purge/delete operations that disrupt processing (availability). It may also trigger unbounded message ingestion, causing cost spikes and consumer overload.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks sqs_queues_not_publicly_accessibleRecommendation
Apply least privilege on SQS resource policies:
- Avoid
Principal: *; grant access only to specific accounts, roles, or services - Add restrictive conditions to tightly scope access
- Prefer private connectivity and defense-in-depth controls
- Review policies and audit activity regularly to prevent drift
Remediation
CLI
aws sqs set-queue-attributes --queue-url <example_queue_url> --attributes Policy='{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"<example_account_id>"},"Action":"sqs:*","Resource":"<example_queue_arn>"}]}'Terraform
# Restrict SQS policy to a specific principal (not public)
resource "aws_sqs_queue_policy" "<example_resource_name>" {
queue_url = "<example_queue_url>"
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { AWS = "<example_account_id>" } # CRITICAL: restrict to a specific principal (removes public "*")
Action = "sqs:*"
Resource = "<example_queue_arn>"
}]
})
}NativeIaC
# CloudFormation: Restrict SQS policy to a specific principal (not public)
Resources:
QueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- "<example_queue_url>"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS: "<example_account_id>" # CRITICAL: restrict access to a specific account (removes public "*")
Action: "sqs:*"
Resource: "<example_queue_arn>"Other
1Open the Amazon SQS console and select the queue
2Go to Permissions (Access policy) and click Edit
3In the JSON policy, replace any "Principal": "*" with "Principal": { "AWS": "<your_account_id>" } or remove those public statements
4Save changes
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.iam.lib.policy import is_condition_block_restrictive
from prowler.providers.aws.services.sqs.sqs_client import sqs_client
class sqs_queues_not_publicly_accessible(Check):
def execute(self):
findings = []
for queue in sqs_client.queues:
report = Check_Report_AWS(metadata=self.metadata(), resource=queue)
report.status = "PASS"
report.status_extended = f"SQS queue {queue.id} is not public."
if queue.policy:
for statement in queue.policy["Statement"]:
# Only check allow statements
if statement["Effect"] == "Allow":
if "Principal" in statement and (
"*" in statement["Principal"]
or (
"AWS" in statement["Principal"]
and "*" in statement["Principal"]["AWS"]
)
or (
"CanonicalUser" in statement["Principal"]
and "*" in statement["Principal"]["CanonicalUser"]
)
):
if "Condition" in statement:
if is_condition_block_restrictive(
statement["Condition"],
sqs_client.audited_account,
True,
):
report.status_extended = f"SQS queue {queue.id} is not public because its policy only allows access from the same account."
else:
report.status = "FAIL"
report.status_extended = f"SQS queue {queue.id} is public because its policy allows public access, and the condition does not limit access to resources within the same account."
break
else:
report.status = "FAIL"
report.status_extended = f"SQS queue {queue.id} is public because its policy allows public access."
break
findings.append(report)
return findings