Back to Checks
DynamoDB table resource-based policy does not allow cross-account access
dynamodb_table_cross_account_access
Service: dynamodbSeverity: medium
OfficialBuilt-inVerified
Categories:trust-boundaries
Resource Type:AwsDynamoDbTable
DynamoDB tables are evaluated for resource-based policies that permit cross-account or public principals.
Tables without a resource policy, or with policies restricted to the same account, are identified as isolated configurations.
Risk
Allowing other accounts to access a table affects:
- Confidentiality: unauthorized reads/data exfiltration
- Integrity: writes or deletes by external principals
- Availability: capacity exhaustion and throttling
- Cost: owner pays for external requests
If public principals are allowed, exposure can be unrestricted.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks dynamodb_table_cross_account_accessRecommendation
Apply least privilege:
- Avoid cross-account data access; if required, allow only named principals
- Constrain with
aws:PrincipalOrgID,aws:SourceVpc,aws:PrincipalArn; addDenyguardrails - Enable Block Public Access and monitor with IAM Access Analyzer
Remediation
CLI
aws dynamodb delete-resource-policy --resource-arn <resource-arn>Other
1Open the AWS Console and go to DynamoDB > Tables
2Select <example_resource_name> and open the Permissions tab
3In Resource-based policy, click Delete policy and confirm
4Save changes to remove any cross-account access
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.dynamodb.dynamodb_client import dynamodb_client
from prowler.providers.aws.services.iam.lib.policy import is_policy_public
class dynamodb_table_cross_account_access(Check):
def execute(self):
findings = []
trusted_account_ids = dynamodb_client.audit_config.get(
"trusted_account_ids", []
)
for table in dynamodb_client.tables.values():
if table.policy is None:
continue
report = Check_Report_AWS(metadata=self.metadata(), resource=table)
report.status = "PASS"
report.status_extended = (
f"DynamoDB table {table.name} does not have a resource-based policy."
)
if table.policy:
report.status_extended = f"DynamoDB table {table.name} has a resource-based policy but is not cross account."
if is_policy_public(
table.policy,
dynamodb_client.audited_account,
is_cross_account_allowed=False,
trusted_account_ids=trusted_account_ids,
):
report.status = "FAIL"
report.status_extended = f"DynamoDB table {table.name} has a resource-based policy allowing cross account access."
findings.append(report)
return findingsReferences
- https://support.icompaas.com/support/solutions/articles/62000233614-ensure-dynamodb-tables-should-not-be-accessible-from-other-aws-accounts
- https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/access-control-resource-based.html
- https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-bpa-rbp.html