Back to Checks
aws

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 Cloud
Run
prowler aws --checks bedrock_api_key_no_administrative_privileges

Recommendation

Enforce least privilege on Bedrock keys:

  • Avoid wildcards like * and bedrock:*; 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 resource

Other

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