AWS Organization has opted out of all AI services and child accounts cannot override the policy
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 Cloudprowler aws --checks organizations_opt_out_ai_services_policyRecommendation
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
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