Back to Checks
aws

AWS Organization restricts operations to only the configured AWS Regions with SCP policies

organizations_scp_check_deny_regions
Service: organizationsSeverity: high
OfficialBuilt-inVerified
Categories:identity-access
Resource Type:Other

AWS Organizations SCPs limit account actions to approved regions using conditions on aws:RequestedRegion.

This evaluates whether policies exist and fully restrict access to the configured allowlist, rather than only some regions.

Risk

Without comprehensive Region limits, users or attackers can deploy resources in ungoverned locations, bypassing monitoring and guardrails.

Impacts:

  • Data outside approved jurisdictions (confidentiality)
  • Policy gaps and drift (integrity)
  • IR blind spots and unexpected cost (availability)

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks organizations_scp_check_deny_regions

Recommendation

Enforce Region governance with SCPs that allow only approved regions via aws:RequestedRegion conditions (deny-by-default).

Apply across relevant OUs and accounts, with narrow exceptions for required global services. Review often; align to least privilege, data residency, and continuous monitoring.

Remediation

Terraform

# Terraform: SCP denying requests outside approved regions
resource "aws_organizations_policy" "<example_resource_name>" {
  name = "<example_resource_name>"
  type = "SERVICE_CONTROL_POLICY"
  content = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        Effect   = "Deny"
        Action   = "*"
        Resource = "*"
        Condition = {
          StringNotEquals = {
            "aws:RequestedRegion" = ["<REGION_1>", "<REGION_2>"] # Critical: only these regions are allowed; others are denied
          }
        }
      }
    ]
  })
}

resource "aws_organizations_policy_attachment" "<example_resource_name>" {
  policy_id = aws_organizations_policy.<example_resource_name>.id
  target_id = "<example_resource_id>" # Critical: attach to the root (r-xxxx), OU (ou-xxxx), or account ID
}

NativeIaC

# CloudFormation: SCP denying requests outside approved regions
Resources:
  <example_resource_name>Policy:
    Type: AWS::Organizations::Policy
    Properties:
      Name: <example_resource_name>
      Type: SERVICE_CONTROL_POLICY
      Content:
        Version: '2012-10-17'
        Statement:
          - Effect: Deny
            Action: "*"
            Resource: "*"
            Condition:
              StringNotEquals:
                aws:RequestedRegion:
                  - <REGION_1>  # Critical: only these regions are allowed; others are denied
                  - <REGION_2>

  <example_resource_name>Attachment:
    Type: AWS::Organizations::PolicyAttachment
    Properties:
      PolicyId: !Ref <example_resource_name>Policy
      TargetId: <example_resource_id>  # Critical: attach SCP to the root/OU/account

Other

1In the AWS Management Console, go to AWS Organizations
2In Policies, ensure Service control policies are Enabled (click Enable if needed)
3Go to Policies > Service control policies > Create policy
4Paste this JSON as the policy content and save:
5{
6"Version": "2012-10-17",
7"Statement": [{
8"Effect": "Deny",
9"Action": "*",
10"Resource": "*",
11"Condition": {"StringNotEquals": {"aws:RequestedRegion": ["<REGION_1>", "<REGION_2>"]}}
12}]
13}
14Attach the policy to the organization root (r-xxxx), target OU, or specific account
15Verify the policy is attached and shows as Applied to the intended target

Check Code

from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.organizations.organizations_client import (
    organizations_client,
)


class organizations_scp_check_deny_regions(Check):
    def execute(self):
        findings = []
        organizations_enabled_regions = organizations_client.audit_config.get(
            "organizations_enabled_regions", []
        )

        if organizations_client.organization:
            if (
                organizations_client.organization.policies is not None
            ):  # Access denied to list policies
                report = Check_Report_AWS(
                    metadata=self.metadata(),
                    resource=organizations_client.organization,
                )
                report.region = organizations_client.region
                report.status = "FAIL"
                report.status_extended = (
                    "AWS Organizations is not in-use for this AWS Account."
                )

                if organizations_client.organization.status == "ACTIVE":
                    report.status_extended = f"AWS Organizations {organizations_client.organization.id} does not have SCP policies."
                    # We use this flag if we find a statement that is restricting regions but not all the configured ones:
                    is_region_restricted_statement = False

                    for policy in organizations_client.organization.policies.get(
                        "SERVICE_CONTROL_POLICY", []
                    ):
                        # Statements are not always list
                        statements = policy.content.get("Statement", [])
                        if type(statements) is not list:
                            statements = [statements]

                        for statement in statements:
                            # Deny if Condition = {"StringNotEquals": {"aws:RequestedRegion": [region1, region2]}}
                            if (
                                statement.get("Effect") == "Deny"
                                and "Condition" in statement
                                and "StringNotEquals" in statement["Condition"]
                                and "aws:RequestedRegion"
                                in statement["Condition"]["StringNotEquals"]
                            ):
                                if all(
                                    region
                                    in statement["Condition"]["StringNotEquals"][
                                        "aws:RequestedRegion"
                                    ]
                                    for region in organizations_enabled_regions
                                ):
                                    # All defined regions are restricted, we exit here, no need to continue.
                                    report.status = "PASS"
                                    report.status_extended = f"AWS Organization {organizations_client.organization.id} has SCP policy {policy.id} restricting all configured regions found."
                                    findings.append(report)
                                    return findings
                                else:
                                    # Regions are restricted, but not the ones defined, we keep this finding, but we continue analyzing:
                                    is_region_restricted_statement = True
                                    report.status = "FAIL"
                                    report.status_extended = f"AWS Organization {organizations_client.organization.id} has SCP policies {policy.id} restricting some AWS Regions, but not all the configured ones, please check config."

                            # Allow if Condition = {"StringEquals": {"aws:RequestedRegion": [region1, region2]}}
                            if (
                                statement.get("Effect") == "Allow"
                                and "Condition" in statement
                                and "StringEquals" in statement["Condition"]
                                and "aws:RequestedRegion"
                                in statement["Condition"]["StringEquals"]
                            ):
                                if all(
                                    region
                                    in statement["Condition"]["StringEquals"][
                                        "aws:RequestedRegion"
                                    ]
                                    for region in organizations_enabled_regions
                                ):
                                    # All defined regions are restricted, we exit here, no need to continue.
                                    report.status = "PASS"
                                    report.status_extended = f"AWS Organization {organizations_client.organization.id} has SCP policy {policy.id} restricting all configured regions found."
                                    findings.append(report)
                                    return findings
                                else:
                                    # Regions are restricted, but not the ones defined, we keep this finding, but we continue analyzing:
                                    is_region_restricted_statement = True
                                    report.status = "FAIL"
                                    report.status_extended = f"AWS Organization {organizations_client.organization.id} has SCP policies {policy.id} restricting some AWS Regions, but not all the configured ones, please check config."

                    if not is_region_restricted_statement:
                        report.status = "FAIL"
                        report.status_extended = f"AWS Organization {organizations_client.organization.id} has SCP policies but don't restrict AWS Regions."

                findings.append(report)

        return findings