Back to Checks
aws

AWS Organization has opted out of all AI services and child accounts cannot override the policy

organizations_opt_out_ai_services_policy
Service: organizationsSeverity: medium
OfficialBuilt-inVerified
Categories:gen-ai
Resource Type:Other

AWS Organizations is assessed for an AI services opt-out policy that sets services.default.opt_out_policy to optOut and blocks child overrides via @@operators_allowed_for_child_policies set to @@none.

Risk

Without an enforced opt-out, AI services may store and use your content for model training, weakening confidentiality and data sovereignty. If child accounts can override, they can re-enable data use, risking unintended cross-Region retention and exposure of logs, documents, or code processed by these services.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler aws --checks organizations_opt_out_ai_services_policy

Recommendation

Establish an org-wide AI services opt-out: set the default to optOut and prohibit child policy overrides (@@none). Apply at the highest scope, gate exceptions through change control, and review periodically. Align with least privilege and data minimization to prevent unintended content sharing with managed AI services.

Remediation

Terraform

# Enable AI services opt-out policy type
resource "aws_organizations_organization" "<example_resource_name>" {
  enabled_policy_types = ["AISERVICES_OPT_OUT_POLICY"]  # Critical: allow AI opt-out policies
}

# Create the AI opt-out policy
resource "aws_organizations_policy" "<example_resource_name>" {
  name    = "<example_resource_name>"
  type    = "AISERVICES_OPT_OUT_POLICY"
  content = <<JSON
{ "services": { "default": { "opt_out_policy": { "@@assign": "optOut", "@@operators_allowed_for_child_policies": ["@@none"] } } } }
JSON
  # Critical: @@assign "optOut" opts out; @@operators... ["@@none"] prevents child overrides
}

# Attach policy to the org root
resource "aws_organizations_policy_attachment" "<example_resource_name>" {
  policy_id = aws_organizations_policy.<example_resource_name>.id
  target_id = aws_organizations_organization.<example_resource_name>.roots[0].id  # Critical: attach to root
}

NativeIaC

# CloudFormation: Opt out of all AI services and prevent child overrides
Resources:
  AiServicesOptOutPolicy:
    Type: AWS::Organizations::Policy
    Properties:
      Name: <example_resource_name>
      Type: AISERVICES_OPT_OUT_POLICY
      Content: |
        { "services": { "default": { "opt_out_policy": { "@@assign": "optOut", "@@operators_allowed_for_child_policies": ["@@none"] } } } }
        # Critical: @@assign "optOut" opts out org-wide; @@operators... ["@@none"] blocks child overrides
      TargetIds:
        - <example_resource_id> # Critical: attach to the organization root (e.g., r-xxxx)

Other

1In the AWS Management Console, open AWS Organizations using the management account
2Go to Policies > AI services opt-out
3Click Opt out from all services and confirm
4Verify the policy is attached to the Root and shows default -> opt_out_policy -> @@assign: optOut with @@operators_allowed_for_child_policies set to ["@@none"]

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_opt_out_ai_services_policy(Check):
    def execute(self):
        findings = []

        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":
                    all_conditions_passed = False
                    opt_out_policies = organizations_client.organization.policies.get(
                        "AISERVICES_OPT_OUT_POLICY", []
                    )

                    if not opt_out_policies:
                        report.status_extended = f"AWS Organization {organizations_client.organization.id} has no opt-out policy for AI services."
                    else:
                        for policy in opt_out_policies:
                            opt_out_policy = (
                                policy.content.get("services", {})
                                .get("default", {})
                                .get("opt_out_policy", {})
                            )

                            condition_1 = opt_out_policy.get("@@assign") == "optOut"
                            condition_2 = opt_out_policy.get(
                                "@@operators_allowed_for_child_policies"
                            ) == ["@@none"]

                            if condition_1 and condition_2:
                                all_conditions_passed = True
                                break

                            if not condition_1 and not condition_2:
                                report.status_extended = f"AWS Organization {organizations_client.organization.id} has not opted out of all AI services and it does not disallow child-accounts to overwrite the policy."
                            elif not condition_1:
                                report.status_extended = f"AWS Organization {organizations_client.organization.id} has not opted out of all AI services."
                            elif not condition_2:
                                report.status_extended = f"AWS Organization {organizations_client.organization.id} has opted out of all AI services but it does not disallow child-accounts to overwrite the policy."

                        if all_conditions_passed:
                            report.status = "PASS"
                            report.status_extended = f"AWS Organization {organizations_client.organization.id} has opted out of all AI services and also disallows child-accounts to overwrite this policy."

                findings.append(report)

        return findings