Techniques
Sample rules
GenAI Prompt Contains Leaked Credential
- source: elastic
- technicques:
- T1552
Description
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.
Detection logic
FROM 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
// gen_ai.*.messages are mapped as flattened, which RLIKE cannot read; TO_STRING returns their JSON text.
| EVAL Esql_priv.all_text = CONCAT(
COALESCE(MV_CONCAT(TO_STRING(gen_ai.input.messages), "\n"), ""), "\n",
COALESCE(MV_CONCAT(TO_STRING(gen_ai.output.messages), "\n"), ""), "\n",
COALESCE(MV_CONCAT(security_ai.encoding.input_messages.strings, "\n"), ""), "\n",
COALESCE(MV_CONCAT(security_ai.encoding.output_messages.strings, "\n"), ""), "\n",
COALESCE(MV_CONCAT(security_ai.hash_string.input_messages.strings, "\n"), ""), "\n",
COALESCE(MV_CONCAT(security_ai.hash_string.output_messages.strings, "\n"), ""))
// Credential formats are split across two RLIKEs because a single pattern with every format exceeds
// ES|QL's regex determinization limit. A key must not be glued to a preceding key character (or be
// preceded by a JSON-escaped \n, \r or \t); that also keeps the automaton small.
// Not lowercased: credential prefixes (AKIA, sk-, ghp_, etc.) are case-significant.
| 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,}).*"""
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-----).*"""
| KEEP _id, _version, _index, @timestamp, gen_ai.*, security_ai.*, aws_bedrock.*, user.*, cloud.*, event.*, openai_chatgpt_enterprise.*