Back to Checks
Amazon Bedrock API key does not have administrative privileges, privilege escalation paths, or full Bedrock service access
bedrock_api_key_no_administrative_privileges
Service: bedrockSeverity: high
OfficialBuilt-inVerified
Categories:gen-aiidentity-access
Resource Type:AwsIamAccessKey
Bedrock API keys linked to IAM users are evaluated for excessive permissions, including policies that grant full access (* or bedrock:*) or enable privilege escalation. The finding highlights keys whose attached or inline policies provide broad or escalating capabilities.
Risk
Over-privileged Bedrock API keys weaken confidentiality, integrity, and availability. If compromised, an attacker could:
- Escalate IAM rights and persist access
- Invoke models at scale to exfiltrate data or incur high costs
- Modify Bedrock settings, disrupting operations
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks bedrock_api_key_no_administrative_privilegesRecommendation
Enforce least privilege on Bedrock keys:
- Avoid wildcards like
*andbedrock:*; allow only required actions - Prevent identity changes by disallowing
iam:* - Prefer short-term credentials with rotation and MFA
- Use permissions boundaries and SCPs as guardrails
- Review usage and tighten policies via access analysis
Remediation
CLI
aws iam delete-service-specific-credential --user-name <username> --service-specific-credential-id <credential-id>Terraform
# Attach a minimal inline policy to the IAM user owning the Bedrock API key
resource "aws_iam_user_policy" "<example_resource_name>" {
name = "least-priv-bedrock"
user = "<example_resource_name>"
# CRITICAL: allow only the specific action required; avoids admin or bedrock:* full access
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Action = ["bedrock:InvokeModel"]
Resource = "*"
}]
})
}NativeIaC
# CloudFormation: attach least-privilege policy to the IAM user owning the Bedrock API key
Resources:
<example_resource_name>:
Type: AWS::IAM::Policy
Properties:
PolicyName: least-priv-bedrock
Users:
- <example_resource_name>
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- bedrock:InvokeModel # CRITICAL: allow only needed Bedrock action to avoid admin or bedrock:* permissions
Resource: "*" # Limits access scope to only InvokeModel on any resourceOther
1Open the AWS Console and go to IAM > Users
2Select the user that owns the Bedrock service-specific credential (Security credentials > Service-specific credentials shows bedrock.amazonaws.com)
3In the Permissions tab, detach any policy granting AdministratorAccess or bedrock:* (e.g., AmazonBedrockFullAccess)
4In the same tab, delete any inline policy that provides admin/privilege-escalation permissions or bedrock:* access
5If Bedrock access is needed, add a minimal policy allowing only bedrock:InvokeModel
6Save changes
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.iam.iam_client import iam_client
from prowler.providers.aws.services.iam.lib.policy import (
check_admin_access,
check_full_service_access,
)
from prowler.providers.aws.services.iam.lib.privilege_escalation import (
check_privilege_escalation,
)
class bedrock_api_key_no_administrative_privileges(Check):
def execute(self):
findings = []
for api_key in iam_client.service_specific_credentials:
if api_key.service_name != "bedrock.amazonaws.com":
continue
report = Check_Report_AWS(metadata=self.metadata(), resource=api_key)
report.status = "PASS"
report.status_extended = f"API key {api_key.id} in user {api_key.user.name} has no administrative privileges."
for policy in api_key.user.attached_policies:
policy_arn = policy["PolicyArn"]
if policy_arn in iam_client.policies:
policy_document = iam_client.policies[policy_arn].document
if policy_document:
if check_admin_access(policy_document):
report.status = "FAIL"
report.status_extended = f"API key {api_key.id} in user {api_key.user.name} has administrative privileges through attached policy {policy['PolicyName']}."
break
elif check_privilege_escalation(policy_document):
report.status = "FAIL"
report.status_extended = f"API key {api_key.id} in user {api_key.user.name} has privilege escalation through attached policy {policy['PolicyName']}."
break
elif check_full_service_access("bedrock", policy_document):
report.status = "FAIL"
report.status_extended = f"API key {api_key.id} in user {api_key.user.name} has full service access through attached policy {policy['PolicyName']}."
break
for inline_policy_name in api_key.user.inline_policies:
inline_policy_arn = f"{api_key.user.arn}:policy/{inline_policy_name}"
if inline_policy_arn in iam_client.policies:
policy_document = iam_client.policies[inline_policy_arn].document
if policy_document:
if check_admin_access(policy_document):
report.status = "FAIL"
report.status_extended = f"API key {api_key.id} in user {api_key.user.name} has administrative privileges through inline policy {inline_policy_name}."
break
elif check_privilege_escalation(policy_document):
report.status = "FAIL"
report.status_extended = f"API key {api_key.id} in user {api_key.user.name} has privilege escalation through inline policy {inline_policy_name}."
break
elif check_full_service_access("bedrock", policy_document):
report.status = "FAIL"
report.status_extended = f"API key {api_key.id} in user {api_key.user.name} has full service access through inline policy {inline_policy_name}."
break
findings.append(report)
return findings