GenAI Prompt Contains Leaked Credential
Detects known credential formats — AWS access key IDs, LLM vendor API keys, GitHub personal access tokens, SSH/PEM private key headers, JWTs, and similar — appearing in GenAI prompt or completion text, or in strings flagged by the security_ai ML model as encoded payloads.
Credentials in the model input mean an application or user is sending secrets to the model, exposing them to invocation logging, the model provider, and prompt history. Credentials in the model output or in ML-extracted encoded blobs indicate either training-data leakage, a poisoned context window, or a prompt-injection-driven exfiltration attempt. Either case warrants immediate credential rotation.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/08/19"
3integration = ["security_ai", "aws_bedrock", "openai_chatgpt_enterprise"]
4maturity = "production"
5min_stack_comments = "Detection rules for the security_ai integration package are supported in v9.6.0 and above"
6min_stack_version = "9.6.0"
7updated_date = "2026/11/06"
8
9[rule]
10author = ["Elastic"]
11description = """
12Detects known credential formats — AWS access key IDs, LLM vendor API keys, GitHub
13personal access tokens, SSH/PEM private key headers, JWTs, and similar — appearing
14in GenAI prompt or completion text, or in strings flagged by the security_ai
15ML model as encoded payloads.
16
17Credentials in the model input mean an application or user is sending secrets to the
18model, exposing them to invocation logging, the model provider, and prompt history.
19Credentials in the model output or in ML-extracted encoded blobs indicate either
20training-data leakage, a poisoned context window, or a prompt-injection-driven
21exfiltration attempt. Either case warrants immediate credential rotation.
22"""
23false_positives = [
24 """
25 Prompts or completions that reference example or documentation keys (for example
26 the AWS sample access key ending in EXAMPLE) match the access-key pattern.
27 Review the matched value in gen_ai.input.messages, gen_ai.output.messages, or
28 security_ai.*.strings and confirm whether it is a live credential
29 before responding.
30 """,
31 """
32 JWTs used as legitimate authentication tokens passed to the model for parsing,
33 validation, or debugging. Inspect the prompt context to confirm whether the
34 token was intentionally shared for a benign purpose.
35 """,
36]
37from = "now-60m"
38interval = "10m"
39language = "esql"
40license = "Elastic License v2"
41name = "GenAI Prompt Contains Leaked Credential"
42note = """
43## Triage and Analysis
44
45### Investigating GenAI Prompt Contains Leaked Credential
46
47This rule fires when a recognized credential format appears in a GenAI invocation's
48prompt, completion, or in strings extracted by the security_ai ML model.
49Credential exposure via LLM invocation logs is a high-impact event: logs may be
50retained by the cloud provider, ingested into SIEM, or replayed in future training runs.
51
52### Possible investigation steps
53
54- Identify the matched credential format from `security_ai.encoding.input_messages.strings`,
55 `security_ai.encoding.output_messages.strings`, `security_ai.hash_string.input_messages.strings`,
56 `security_ai.hash_string.output_messages.strings`, `gen_ai.input.messages`, or `gen_ai.output.messages`.
57 Common format signals:
58 - `AKIA`/`ASIA` prefix (20 chars) → AWS long-term or STS access key ID
59 - `sk-ant-api03-` → Anthropic API key
60 - `sk-proj-` / `sk-` (48+ chars) → OpenAI API key
61 - `AIza` → Google API key
62 - `ghp_`/`gho_`/`ghu_`/`ghs_` → GitHub personal/OAuth/user/server access token
63 - `github_pat_` → GitHub fine-grained personal access token
64 - `glpat-` → GitLab personal access token
65 - `sk_live_` → Stripe live secret key
66 - `hf_` → HuggingFace access token
67 - `xox[baprs]-` → Slack bot/app/personal/incoming-webhook/refresh token
68 - Three dot-separated base64url segments starting with `eyJ` → JWT
69 - `-----BEGIN ... PRIVATE KEY-----` → SSH, RSA, EC, or PKCS8 private key
70
71- Check `gen_ai.input.messages` and `gen_ai.output.messages` for the full conversation context.
72 Determine whether the credential appeared in user input (exfiltration attempt or
73 accidental exposure) or in the model's response (leakage or injection-driven retrieval).
74
75- Identify the caller: `user.id`, `source.ip`, `user_agent.original`,
76 `aws_bedrock.invocation.model_id`.
77
78- If the credential appears in the ML-extracted strings (`security_ai.*.{input_messages,output_messages}.strings`),
79 also check whether a co-occurring base64 rule alert fired. The base64 alert is
80 suppressed when credentials are present, so if it did not fire, the credential was
81 the only encoded content.
82
83- Query CloudTrail or the relevant provider's audit logs for any use of the exposed
84 credential within the alert window.
85
86### False positive analysis
87
88- AWS sample/documentation keys (ending in `EXAMPLE`) match the AKIA pattern.
89 Confirm the value is real before escalating.
90- JWTs passed deliberately for debugging are common. Check whether the model was
91 being asked to validate, decode, or inspect the token.
92
93### Response and remediation
94
95- Rotate or revoke the exposed credential immediately, regardless of whether it
96 appears to have been used.
97- Identify the application or workflow that placed the credential in the prompt and
98 remediate the root cause (secrets scanning, environment variable hygiene, guardrails).
99- If the credential appears in the model's completion, assess whether this is a
100 training-data leakage, a context-window injection, or a configuration error.
101- Review the full invocation history for the affected user or application to identify
102 any pattern of credential exposure.
103"""
104references = [
105 "https://owasp.org/www-project-top-10-for-large-language-model-applications/",
106 "https://www.beyondtrust.com/blog/entry/aws-bedrock-security-guide-api-keys-detection-response",
107]
108risk_score = 73
109rule_id = "e3b1f8c4-7d2a-4e5b-9c1a-6f8d3b2e7a0c"
110setup = """This rule requires the security_ai Fleet integration. Install the
111integration and ensure that the ML model pipeline is enriching invocation events before
112enabling this rule. The rule also scans gen_ai.input.messages and gen_ai.output.messages directly,
113so it will partially function (message scanning only) even without the
114ML pipeline enrichment. For setup instructions, refer to the [Security for AI integration documentation](https://www.elastic.co/docs/reference/integrations/security_ai)."""
115severity = "high"
116tags = [
117 "Domain: GenAI",
118 "Use Case: Security for AI",
119 "Tactic: Credential Access",
120 "Mitre Atlas: AML.T0055",
121 "Data Source: AWS Bedrock",
122 "Data Source: OpenAI ChatGPT Enterprise",
123 "Platform: AWS",
124 "Platform: OpenAI",
125 "Service: AWS Bedrock",
126 "Service: OpenAI ChatGPT Enterprise",
127 "Rule Type: ES|QL",
128 "Resources: Investigation Guide",
129]
130timestamp_override = "event.ingested"
131to = "now"
132type = "esql"
133
134query = '''
135FROM logs-aws_bedrock.invocation-*, logs-openai_chatgpt_enterprise.codex_log-*, logs-openai_chatgpt_enterprise.conversation_message-*, logs-openai_chatgpt_enterprise.custom_agents_log-* METADATA _id, _version, _index
136// gen_ai.*.messages are mapped as flattened, which RLIKE cannot read; TO_STRING returns their JSON text.
137| EVAL Esql_priv.all_text = CONCAT(
138 COALESCE(MV_CONCAT(TO_STRING(gen_ai.input.messages), "\n"), ""), "\n",
139 COALESCE(MV_CONCAT(TO_STRING(gen_ai.output.messages), "\n"), ""), "\n",
140 COALESCE(MV_CONCAT(security_ai.encoding.input_messages.strings, "\n"), ""), "\n",
141 COALESCE(MV_CONCAT(security_ai.encoding.output_messages.strings, "\n"), ""), "\n",
142 COALESCE(MV_CONCAT(security_ai.hash_string.input_messages.strings, "\n"), ""), "\n",
143 COALESCE(MV_CONCAT(security_ai.hash_string.output_messages.strings, "\n"), ""))
144// Credential formats are split across two RLIKEs because a single pattern with every format exceeds
145// ES|QL's regex determinization limit. A key must not be glued to a preceding key character (or be
146// preceded by a JSON-escaped \n, \r or \t); that also keeps the automaton small.
147// Not lowercased: credential prefixes (AKIA, sk-, ghp_, etc.) are case-significant.
148| WHERE Esql_priv.all_text RLIKE """(.*([^A-Za-z0-9_\-]|\\[nrt]))?((AKIA|ASIA|ABIA|ACCA)[A-Z0-9]{16}|ABSK[A-Za-z0-9+/=]{20}|AIza[0-9A-Za-z_\-]{35}|gh[pousr]_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{22,}|glpat-[A-Za-z0-9_\-]{20,}|sk-ant-api03-[A-Za-z0-9_\-]{80,}|sk-proj-[A-Za-z0-9_\-]{20,}).*"""
149 OR Esql_priv.all_text RLIKE """(.*([^A-Za-z0-9_\-]|\\[nrt]))?(sk-[A-Za-z0-9]{48}|sk_live_[A-Za-z0-9]{24}|hf_[A-Za-z0-9]{34}|xox[baprs]-[A-Za-z0-9\-]{10,}|eyJ[A-Za-z0-9_\-]{10,}\.eyJ[A-Za-z0-9_\-]{10,}\..*|-----BEGIN [A-Z ]*PRIVATE KEY-----).*"""
150| KEEP _id, _version, _index, @timestamp, gen_ai.*, security_ai.*, aws_bedrock.*, user.*, cloud.*, event.*, openai_chatgpt_enterprise.*
151'''
152
153[[rule.threat]]
154framework = "MITRE ATT&CK"
155
156[[rule.threat.technique]]
157id = "T1552"
158name = "Unsecured Credentials"
159reference = "https://attack.mitre.org/techniques/T1552/"
160
161[rule.threat.tactic]
162id = "TA0006"
163name = "Credential Access"
164reference = "https://attack.mitre.org/tactics/TA0006/"
165
166[[rule.threat_mappings]]
167framework = "MITRE ATLAS"
168version = "2026.08"
169
170[[rule.threat_mappings.threat]]
171framework = "MITRE ATLAS"
172
173[[rule.threat_mappings.threat.technique]]
174id = "AML.T0055"
175name = "Unsecured Credentials"
176reference = "https://atlas.mitre.org/techniques/AML.T0055/"
177
178[rule.threat_mappings.threat.tactic]
179id = "AML.TA0013"
180name = "Credential Access"
181reference = "https://atlas.mitre.org/tactics/AML.TA0013/"
Triage and Analysis
Investigating GenAI Prompt Contains Leaked Credential
This rule fires when a recognized credential format appears in a GenAI invocation's prompt, completion, or in strings extracted by the security_ai ML model. Credential exposure via LLM invocation logs is a high-impact event: logs may be retained by the cloud provider, ingested into SIEM, or replayed in future training runs.
Possible investigation steps
-
Identify the matched credential format from
security_ai.encoding.input_messages.strings,security_ai.encoding.output_messages.strings,security_ai.hash_string.input_messages.strings,security_ai.hash_string.output_messages.strings,gen_ai.input.messages, orgen_ai.output.messages. Common format signals:AKIA/ASIAprefix (20 chars) → AWS long-term or STS access key IDsk-ant-api03-→ Anthropic API keysk-proj-/sk-(48+ chars) → OpenAI API keyAIza→ Google API keyghp_/gho_/ghu_/ghs_→ GitHub personal/OAuth/user/server access tokengithub_pat_→ GitHub fine-grained personal access tokenglpat-→ GitLab personal access tokensk_live_→ Stripe live secret keyhf_→ HuggingFace access tokenxox[baprs]-→ Slack bot/app/personal/incoming-webhook/refresh token- Three dot-separated base64url segments starting with
eyJ→ JWT -----BEGIN ... PRIVATE KEY-----→ SSH, RSA, EC, or PKCS8 private key
-
Check
gen_ai.input.messagesandgen_ai.output.messagesfor the full conversation context. Determine whether the credential appeared in user input (exfiltration attempt or accidental exposure) or in the model's response (leakage or injection-driven retrieval). -
Identify the caller:
user.id,source.ip,user_agent.original,aws_bedrock.invocation.model_id. -
If the credential appears in the ML-extracted strings (
security_ai.*.{input_messages,output_messages}.strings), also check whether a co-occurring base64 rule alert fired. The base64 alert is suppressed when credentials are present, so if it did not fire, the credential was the only encoded content. -
Query CloudTrail or the relevant provider's audit logs for any use of the exposed credential within the alert window.
False positive analysis
- AWS sample/documentation keys (ending in
EXAMPLE) match the AKIA pattern. Confirm the value is real before escalating. - JWTs passed deliberately for debugging are common. Check whether the model was being asked to validate, decode, or inspect the token.
Response and remediation
- Rotate or revoke the exposed credential immediately, regardless of whether it appears to have been used.
- Identify the application or workflow that placed the credential in the prompt and remediate the root cause (secrets scanning, environment variable hygiene, guardrails).
- If the credential appears in the model's completion, assess whether this is a training-data leakage, a context-window injection, or a configuration error.
- Review the full invocation history for the affected user or application to identify any pattern of credential exposure.
References
Related rules
- GenAI Prompt Contains Base64-Encoded Payload
- GenAI Prompt Contains Cryptographic Hash String
- High Confidence Malicious GenAI Assistant Response
- High Confidence Prompt Injection in a GenAI User Message
- OpenAI ChatGPT Enterprise Assistant Advises Credential Rotation After Suspected Exposure