Safeguard
Security Guides•

How do you write an SNS to SQS queue policy without a confused deputy gap?

Allow the SNS service to send to your SQS queue, then add an aws:SourceArn or aws:SourceAccount condition so only your topic can. Example and checks.

Safeguard Security Team
3 min read

Grant the SNS service principal permission to call sqs:SendMessage on your queue, then add an aws:SourceArn condition with your topic's ARN, or aws:SourceAccount if the queue subscribes to several topics. Without the condition, a topic in someone else's account might be able to push messages into your queue.

The confused deputy problem in plain words

A confused deputy is a service that has permission to act and is tricked into using it for the wrong party. Here the deputy is SNS. Your queue policy says "SNS may send messages to this queue." If that is all it says, the statement is true for any SNS topic, including topics you do not own.

AWS's IAM documentation recommends using aws:SourceArn, aws:SourceAccount, aws:SourceOrgID or aws:SourceOrgPaths in resource policies whenever a service principal is granted access to one of your resources. These keys let the policy check that the service acts on behalf of the resource, account or organization you expect.

The policy

The SNS developer guide gives this pattern. The principal is the SNS service and the condition ties the permission to a specific topic:

{
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "Service": "sns.amazonaws.com" },
      "Action": "sqs:SendMessage",
      "Resource": "arn:aws:sqs:us-east-2:123456789012:MyQueue",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:sns:us-east-2:123456789012:MyTopic"
        }
      }
    }
  ]
}

The ARNs and account number in this example are placeholders from AWS documentation. Replace them with your own.

Steps

  1. Get the queue ARN and the topic ARN from the console or from the attribute APIs.
  2. Write one policy statement per topic if the queue subscribes to several. The SNS documentation says the policy must contain one statement for each topic.
  3. Use aws:SourceArn for a single topic. If you subscribe the queue to many topics, aws:SourceAccount keeps the policy shorter, with the tradeoff that every topic in that account is allowed.
  4. Apply the policy in the SQS console on the access policy tab, or with the SetQueueAttributes API.
  5. Subscribe the queue to the topic and send a test message.
  6. Test the negative case. A message published from a topic that does not match the condition should not arrive.

Existing queues need a review

Older policies were often written without the condition, or with a wildcard principal because it was the fastest way to make a subscription work. List your queues, read each access policy, and look for statements that name the SNS service without a source condition or use a principal of star. Pay particular attention to queues in accounts that receive messages from other accounts, as the cross-account case is where an unconditioned statement matters most.

If you manage queues through infrastructure as code, add a check in the pull request that fails when a service principal statement lacks a source condition. See How do you stop a risky broker config change in a pull request? for a pattern.

Safeguard's policies and gates can enforce rules like this on pull requests, and the free scan can start you off with your dependency inventory.

Quick check

Should I use aws:SourceArn or aws:SourceAccount?

SourceArn is narrower, tying access to one topic. SourceAccount works when the queue serves several topics in one account. AWS documents both for the SNS to SQS case.

Does the condition replace encryption or message validation?

No. It controls who may send. Still encrypt the queue and validate message contents in the consumer.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.