The AWS Bedrock API Keys Security Guide Part 2: Detection, Prevention, and Response


Executive Summary
This guide offers further documentation on the security risks introduced by the authentication method AWS launched in July 2025 for Amazon Bedrock. Part 1 of this series documented the risks of AWS Bedrock API keys: phantom IAM users with administrative permissions, the misleading scope of AmazonBedrockLimitedAccess, and LLMjacking exposure of up to $18,000/day per region. Part 2 will cover detection, prevention, incident response, and migration to STS.
Detection Strategies
CloudTrail is the primary detection layer for Bedrock API key abuse. This section covers detection signals, events to monitor, and deployment guidance for CloudWatch, EventBridge, and SIEM platforms.
The Primary Signal: callWithBearerToken
When recorded in CloudTrail, every Bedrock API key request carries `additionalEventData.callWithBearerToken = true`. SigV4-authenticated requests do not. The field is the definitive signal for both long-term and short-term keys.

Figure 1: CloudTrail event recorded when a Bedrock API key is used. The callWithBearerToken: true field (highlighted) within additionalEventData is the primary detection signal. Note the userIdentity section showing the phantom IAM user BedrockAPIKey-826f as the caller, along with the source IP address and user agent string.
Note: InvokeModel, InvokeModelWithResponseStream, Converse, and ConverseStream (the typical LLMjacking targets) are logged as management events and captured by default. Agent, Knowledge Base, Flow, async-invoke, and Guardrail calls (InvokeAgent, Retrieve, RetrieveAndGenerate, InvokeFlow, ApplyGuardrail, etc.) are logged as data events and require advanced event selectors on the trail.
What to Monitor
Four CloudTrail events to monitor:
API key creation: A CreateServiceSpecificCredential event with serviceName = "bedrock.amazonaws.com"
Phantom user creation: A CreateUser event where the userName starts with BedrockAPIKey-.
API key usage: Any Bedrock action where additionalEventData.callWithBearerToken = true
Access key escalation (CRITICAL): `CreateAccessKey` with `userName` prefix `BedrockAPIKey-`. This is the privilege-escalation pivot from Part 1.
The following table maps the highest-priority alerting scenarios derived from these events to severity and response times:
CloudTrail Event | Severity | Action Required | Response Time |
|---|---|---|---|
CreateAccessKey on BedrockAPIKey-* user | CRITICAL | Investigate immediately | <5 minutes |
callWithBearerToken=true from unknown IP | HIGH | Verify legitimacy | <15 minutes |
CreateServiceSpecificCredential for Bedrock | MEDIUM | Audit & document | <1 hour |
CreateUser with BedrockAPIKey-* prefix | MEDIUM | Audit & document | <1 hour |
callWithBearerToken=true during off-hours | MEDIUM | Review patterns | <1 hour |
NA
Deployment: CloudWatch Logs Insights
If you use AWS-native monitoring without an external SIEM, this CloudWatch Logs Insights query surfaces all Bedrock API key activity from CloudTrail:
fields @timestamp, userIdentity.principalId, sourceIPAddress, eventName
| filter additionalEventData.callWithBearerToken = true
| stats count() by eventName, userIdentity.principalId
| sort count desc
Set a CloudWatch alarm that triggers when this query returns more than 100 results per hour. Adjust the threshold based on your environment's normal Bedrock API key usage volume.
BKS provides this query at `detections/cloudwatch-insights/bearer-token-usage.txt`.
Deployment: EventBridge
EventBridge provides a universal routing mechanism that can send alerts to SNS topics (email/SMS), Lambda functions (custom automation), CloudWatch Log Groups (centralized logging), or third-party SIEMs via EventBridge API destinations.
The following pattern is the visibility baseline. It matches every Bedrock API call authenticated with a bearer token (long-term ABSK or short-term bedrock-api-key-) on the runtime APIs captured by default (InvokeModel, InvokeModelWithResponseStream, Converse, ConverseStream):
{
"source": ["aws.bedrock"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"additionalEventData": {
"callWithBearerToken": [true]
}
}
}
For the privilege-escalation pivot called out earlier, pair the visibility baseline above with the IAM-lifecycle pattern below. It fires on every iam:CreateAccessKey targeting a BedrockAPIKey-* user. In most environments there is no legitimate reason for that combination, so any match warrants immediate response:
{
"source": ["aws.iam"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": {
"eventSource": ["iam.amazonaws.com"],
"eventName": ["CreateAccessKey"],
"requestParameters": {
"userName": [{"prefix": "BedrockAPIKey-"}]
}
}
}
If you don't have full SIEM integration yet, an EventBridge rule routing to an SNS topic provides immediate alerting with minimal setup.
BKS provides five EventBridge patterns at detections/eventbridge/ covering Bedrock API key usage and creation, phantom user creation, AKIA escalation, and console-login pivot.
Deployment: Generic SIEM
For any SIEM platform that ingests CloudTrail events, the following detection rules provide a starting point.
Baseline API key usage detection:
filter: additionalEventData.callWithBearerToken = true
threshold: adjust based on environment baseline
severity: medium (escalate if source IP is outside known ranges)
Privilege escalation detection:
filter: eventName = "CreateAccessKey"
AND requestParameters.userName STARTS WITH "BedrockAPIKey-"
severity: high
threshold: any occurrence
Anomalous usage detection:
filter: additionalEventData.callWithBearerToken = true
AND sourceIPAddress NOT IN [known_corporate_ranges]
AND eventTime OUTSIDE [normal_operating_hours]
severity: high
Bedrock-specific signals to weight heavily when tuning: legitimate traffic typically uses AWS SDK user agents and is `InvokeModel`-heavy; observed LLMjacking traffic uses generic clients (`python-requests`, `aiohttp`, `curl`) and includes destructive actions, like `DeleteGuardrail` or `DeleteModel`.
BKS provides six Sigma rules at `detections/sigma/`, two CloudTrail Lake queries at `detections/cloudtrail-lake/`, and two Athena queries at `detections/athena/` covering the same patterns described in the rules above.
Defense Controls
Service Control Policies
Service Control Policies (SCPs) are the primary preventive control for Bedrock API key risks. The appropriate SCP depends on whether you need Bedrock API keys at all.
If you don't use Bedrock API keys, deploy a lockdown SCP that denies both `iam:CreateServiceSpecificCredential` (creation) and `bedrock:CallWithBearerToken` (usage) across the organization.

Figure 2. Complete lockdown SCP. Denies both iam:CreateServiceSpecificCredential and bedrock:CallWithBearerToken, preventing Bedrock API key creation and usage across the organization. Template: https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/1-block-all-keys.json
Deploy via AWS Organizations:
- aws organizations create-policy \
--name Block-Bedrock-API-Keys \
--type SERVICE_CONTROL_POLICY \
--content file: - deny-bedrock-keys.json
aws organizations attach-policy \
--policy-id p-xxxxx \
--target-id r-xxxx # Organization root or specific OU
If you need Bedrock API keys but want to block the phantom-user surface, deny `bedrock:CallWithBearerToken` only when `bedrock:BearerTokenType = LONG_TERM`. Short-term keys (12-hour max) keep working; long-term keys are blocked.

Figure 3. Long-term key restriction SCP. Denies bedrock:CallWithBearerToken only when bedrock:BearerTokenType equals LONG_TERM, allowing short-term keys to function normally. Template: https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/3-block-long-term-only.json
If you permit long-term keys but want a hard expiry, deny `iam:CreateServiceSpecificCredential` when `iam:ServiceSpecificCredentialAgeDays` exceeds 90. This blocks "never expires" and any lifetime over 90 days.

Figure 4. Maximum expiry enforcement SCP. Denies key creation when iam:ServiceSpecificCredentialAgeDays exceeds 90, preventing keys that never expire or have lifetimes beyond 90 days. Template: https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/2-enforce-90day-max.json
Regardless of which creation policy is deployed, also deploy a separate SCP that denies `iam:CreateAccessKey` on all `BedrockAPIKey-*` users. This blocks the privilege escalation path described in Part 1, where an attacker creates standard IAM access keys for phantom users to gain cross-service reconnaissance capabilities outside the Bedrock authentication boundary.

Figure 5. Phantom user access key denial SCP. Denies iam:CreateAccessKey on resources matching arn:aws:iam::*:user/BedrockAPIKey-*, blocking the privilege escalation path through phantom users. Template: https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/4-block-phantom-access-keys.json
Note: AWS added the condition keys used above on September 4, 2025: `iam:ServiceSpecificCredentialServiceName`, `iam:ServiceSpecificCredentialAgeDays`, and `bedrock:BearerTokenType`. If you deployed Bedrock SCPs before September 4, 2025, ensure they use these condition keys for the targeted scoping shown above. New deployments should use them by default.
All four SCPs are deployable as Terraform or CloudFormation from github.com/BeyondTrust/bedrock-keys-security/tree/main/scps
Deployment order: if you have no Bedrock API keys yet, deploy SCPs first. If you already have active keys, deploy detection first (above), then layer SCPs.
Model Invocation Logging
Model invocation logging provides forensic visibility into all Bedrock model calls, including the prompts submitted and responses returned. As documented in Part 1, attackers systematically check whether logging is enabled before beginning exploitation, and accounts with active logging are frequently skipped.
aws bedrock put-model-invocation-logging-configuration \
--logging-config '{
"cloudWatchConfig": {
"logGroupName": "/aws/bedrock/modelinvocations",
"roleArn": "arn:aws:iam::ACCOUNT:role/BedrockLoggingRole"
},
"textDataDeliveryEnabled": true,
"imageDataDeliveryEnabled": false,
"embeddingDataDeliveryEnabled": false
}'
Model invocation logging captures all prompt and response content, which may include sensitive data. Evaluate logging based on data classification:
High-security environments: enable logging for forensic evidence, deterrent effect, and full auditability of model interactions.
Compliance-restricted environments: evaluate carefully based on data classification.
Production environments processing PII: consider whether alternative monitoring (such as CloudTrail-only detection without prompt logging) provides sufficient coverage.
Incident Response
Long-term Key Compromise
Three response options for a compromised long-term Bedrock API key, ordered from fastest to most thorough:
Option 1: Inline deny policy (fastest)
Attach an inline deny policy to the phantom user. This blocks all Bedrock API key usage for that user within seconds, without needing to identify the specific credential ID:

Figure 6. Immediate revocation of a long-term Bedrock API key by attaching an inline deny policy to the phantom user (top), followed by verification showing the key is now rejected with an explicit deny error (bottom).
Option 2: Credential deactivation (reversible)
Identify the specific service-specific credential ID, then set its status to Inactive. The key can be reactivated later if the compromise turns out to be a false positive.

Figure 7. Credential deactivation process. The service-specific credential is listed to obtain its ID (top), deactivated by setting status to Inactive (middle), and verified by confirming the key is rejected with an authentication failure (bottom).
Option 3: Permanent deletion (irreversible)
Delete the credential. This is appropriate when the key is confirmed compromised and no longer needed.

Figure 8. Permanent credential deletion and verification. The service-specific credential is deleted, and a subsequent API call confirms the key is no longer valid.
Regardless of which option is used, check whether IAM access keys have been created for the phantom user. If an attacker exploited the privilege escalation path described in Part 1, IAM access keys must also be revoked:
# Find them
aws iam list-access-keys --user-name BedrockAPIKey-xxxx
# Delete them
aws iam delete-access-key \
--user-name BedrockAPIKey-xxxx \
--access-key-id AKIA...
BKS automates the full revocation sequence (inline deny policy, service-specific credential deletion, and IAM access key disablement) in a single command:
`bks revoke-key BedrockAPIKey-xxxx`.
For forensics, `bks timeline BedrockAPIKey-xxxx --all-regions` reconstructs CloudTrail activity across regions and `bks report BedrockAPIKey-xxxx` writes a full incident report.
Short-term Key Compromise
Short-term keys cannot be deleted or deactivated because they are generated client-side as presigned URLs with a maximum 12-hour lifetime. Response options focus on blocking the key's ability to authenticate.
The recommended approach is to attach an inline deny policy on `bedrock:CallWithBearerToken` to the IAM role that was used to generate the short-term key. This blocks the compromised key immediately, even though the presigned URL still technically exists until expiration.

Figure 9. Short-term key revocation by attaching a deny policy to the IAM role that generated the key. This blocks all Bedrock API key usage through that role.
The alternative is full session revocation, which invalidates all sessions issued by that role before a specified timestamp. This is effective but disruptive: it terminates all active sessions from the role, not just the one that generated the compromised key. Use this option with caution in production where other workloads depend on the same role.
aws iam put-role-policy --role-name <role-name> \
--policy-name RevokeOlderSessions \
--policy-document '{
"Statement": [{
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"DateLessThan": {
"aws:TokenIssueTime": "2026-04-26T18:00:00Z"
}
}
}]
}'
Warning: Session revocation terminates all sessions from the affected role issued before the specified timestamp. This includes legitimate workloads. Verify the blast radius before executing in production.
BKS handles short-term key revocation via the same command:
bks revoke-key bedrock-api-key-XXX
The toolkit detects the key format and applies the appropriate aws:TokenIssueTime deny on the issuing principal.
Phantom User Cleanup
The Bedrock Keys Security (BKS) toolkit automates phantom user discovery and cleanup. It enumerates all BedrockAPIKey-* users in the account, checks each for active service-specific credentials and IAM access keys, and safely removes only orphaned users with no remaining credentials. Users with IAM access keys are flagged for manual review rather than deleted, to preserve forensic evidence of potential privilege escalation.
bks cleanup --dry-run # preview what would be deleted
bks cleanup # delete with confirmation prompt
bks cleanup --force # skip confirmation (use with caution)
Run cleanup monthly to prevent phantom user accumulation.
Migration to AWS STS
STS temporary credentials are the recommended replacement. They expire in 1-12 hours, create no IAM users, use SigV4 signing, and scope through IAM role policies. They eliminate the entire class of risks in this guide: phantom users, policy scoping gaps, privilege escalation, bearer-token exposure.
Assume a role that has the necessary Bedrock permissions, export the returned temporary credentials, and use Bedrock through any standard AWS SDK or CLI:
# Assume a role with Bedrock permissions
aws sts assume-role \
--role-arn arn:aws:iam::ACCOUNT:role/BedrockRole \
--role-session-name bedrock-session \
--duration-seconds 3600
# Export the temporary credentials
export AWS_ACCESS_KEY_ID=ASIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...
# Use Bedrock normally
aws bedrock-runtime converse \
--model-id us.anthropic.claude-opus-4-7 \
--messages '[{"role":"user","content":[{"text":"hello"}]}]'
If you cannot fully migrate from Bedrock API keys, these controls reduce risk:
Short-term keys only: 12-hour maximum to avoid phantom user creation.
CloudTrail alerts: monitor all API key usage through alerts on the callWithBearerToken signal.
SCPs against escalation: block IAM access key creation on phantom users to prevent the privilege escalation path.
Frequent rotation: rotate keys monthly at minimum.
Model invocation logging: enable as both a detective control and an attacker deterrent.
Among these, the SCP denying `bedrock:CallWithBearerToken` is the highest-impact control.
Immediate Action Guide
Step 1: Audit for Phantom Users
Run the Bedrock Keys Security (BKS) toolkit to scan the account for phantom IAM users:
bks scan
Alternatively, query IAM directly:
aws iam list-users | grep BedrockAPIKey
If either command returns results, phantom users exist in the account. For each one found, check its credential status:
aws iam list-service-specific-credentials --user-name BedrockAPIKey-xxx
aws iam list-access-keys --user-name BedrockAPIKey-xxx
The results determine the risk level and required action:
Active service-specific credentials present: the phantom user is operational and the associated Bedrock API key is still in use.
No credentials remain: the user is an orphaned phantom that is safe to clean up using bks cleanup.
IAM access keys (AKIA...) present: the privilege-escalation path is exploited or prepared. Investigate immediately.
Step 2: Deploy Detection
Configure CloudTrail monitoring for four event patterns:
API key creation: `CreateServiceSpecificCredential` events with `serviceName = bedrock.amazonaws.com`.
API key usage: any Bedrock action where `additionalEventData.callWithBearerToken = true`.
Phantom user creation: `CreateUser` events where the `userName` starts with `BedrockAPIKey-`.
Privilege escalation (CRITICAL): `CreateAccessKey` events targeting `BedrockAPIKey-*` users.
The Detection Strategies section provides query templates for CloudWatch Logs Insights, EventBridge, and generic SIEM platforms.
Step 3: Implement Prevention
If you don't need Bedrock API keys, deploy an SCP that denies both `iam:CreateServiceSpecificCredential` and `bedrock:CallWithBearerToken` across the organization (template: https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/1-block-all-keys.json).
Step 4: Restrict If Required
If you need Bedrock API keys:
Maximum 90-day expiry: use the iam:ServiceSpecificCredentialAgeDays condition key to prevent keys that never expire (template: https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/2-enforce-90day-max.json).
CloudTrail alerts: monitor all usage through alerts on the callWithBearerToken signal.
Monthly rotation: rotate keys monthly at minimum.
Block phantom escalation: deploy an SCP to block iam:CreateAccessKey on BedrockAPIKey-* users (https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/4-block-phantom-access-keys.json)
Short-term over long-term: prefer short-term keys to avoid phantom user creation entirely (https://github.com/BeyondTrust/bedrock-keys-security/blob/main/scps/3-block-long-term-only.json)
Migrate to STS where feasible (see Migration to AWS STS).
Conclusion
Bedrock API keys solve a real integration problem but introduce a class of risks that most organizations are not equipped to detect by default:
Phantom IAM users persist beyond the credential lifecycle, accumulating in accounts with no automated cleanup.
The AmazonBedrockLimitedAccess policy grants administrative Bedrock control plus IAM, VPC and KMS reconnaissance, despite its name.
A privilege-escalation pivot exists through iam:CreateAccessKey on phantom users, exposing the full policy scope outside the Bedrock authentication boundary.
The detection signals, preventive SCPs and incident response procedures in this guide cover the full lifecycle. Highest-impact controls in priority order:
AWS STS temporary credentials. The recommended replacement; eliminates the entire class of risk documented across both parts of this guide.
SCP denying bedrock:CallWithBearerToken. The single highest-impact preventive control where Bedrock API keys are unavoidable.
SCP denying iam:CreateAccessKey on BedrockAPIKey-* users. Closes the privilege-escalation pivot.
CloudTrail alerting on additionalEventData.callWithBearerToken = true. The foundational detection signal; layer higher-confidence rules on top.
For organizations with active Bedrock API key usage, run bks scan first to discover existing phantom IAM users, then implement detection before deploying SCPs that may break in-flight workflows.
Resources
Open-source Toolkit and Templates
Bedrock Keys Security Toolkit: https://github.com/BeyondTrust/bedrock-keys-security
Detection Content: https://github.com/BeyondTrust/bedrock-keys-security/tree/main/detections
AWS Official Documentation
Bedrock API Keys User Guide:
https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html
AWS Security Blog: Securing Bedrock API Keys:
https://aws.amazon.com/blogs/security/securing-amazon-bedrock-api-keys-best-practices-for-implementation-and-management/
Service-Specific Credentials:
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_service-specific-creds.html
AWS Security Token Service (STS):
https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html
CloudTrail Event Reference:
https://docs.aws.amazon.com/bedrock/latest/userguide/logging-using-cloudtrail.html
Model Invocation Logging: https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html
AWS Service Control Policies (Organizations): https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html
Explore More Research from Phantom Labs
Phantom Labs™ researchers "think like attackers" to expose privilege escalation paths and identity attack vectors, helping defenders proactively uncover misconfigurations and detect threats in complex hybrid and cloud environments. Using advanced graph modeling, Phantom Labs researchers map attack paths to privileged access across cloud and on-premises infrastructure.

