GCP Vertex AI Elevated Safety Rating on Response
Detects Vertex AI prompt-response logs where a candidate safety_ratings.probability is HIGH or MEDIUM. Those values are stronger signals than NEGLIGIBLE or LOW alone. Requires the request to include safetySettings so ratings are logged.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/10/02"
3integration = ["gcp_vertexai"]
4maturity = "production"
5min_stack_comments = "gcp_vertexai prompt_response_logs requires integration 1.4.0+ (Kibana ^9.2.0)."
6min_stack_version = "9.3.0"
7updated_date = "2026/10/02"
8
9[rule]
10author = ["Elastic"]
11description = """
12Detects Vertex AI prompt-response logs where a candidate safety_ratings.probability is HIGH or MEDIUM. Those values are
13stronger signals than NEGLIGIBLE or LOW alone. Requires the request to include safetySettings so ratings are logged.
14"""
15false_positives = [
16 """
17 Borderline creative-writing or news-summarization prompts can occasionally score MEDIUM. Confirm category and prompt
18 text before escalating.
19 """,
20]
21from = "now-60m"
22interval = "10m"
23language = "esql"
24license = "Elastic License v2"
25name = "GCP Vertex AI Elevated Safety Rating on Response"
26note = """## Triage and analysis
27
28### Investigating GCP Vertex AI Elevated Safety Rating on Response
29
30A GenerateContent response included `safety_ratings.probability` of HIGH or MEDIUM for one or more
31Gemini harm categories (for example `HARM_CATEGORY_HATE_SPEECH` or
32`HARM_CATEGORY_DANGEROUS_CONTENT`). That is a stronger signal than NEGLIGIBLE/LOW and often means
33the prompt probed disallowed content — whether or not generation was fully blocked.
34
35#### Possible investigation steps
36
37- Read the prompt in `gcp.vertexai.prompt_response_logs.full_request.contents.parts.text`.
38- Note `safety_ratings.category`, `probability`, and `severity` on the alert, plus
39 `finish_reason`. `SAFETY` with HIGH/MEDIUM is high confidence; `STOP` with HIGH still warrants
40 review of what was returned.
41- Check `full_request.safety_settings.threshold` on the same event. `BLOCK_NONE` means category
42 blocking was disabled for listed categories.
43- Pivot to `logs-gcp_vertexai.auditlogs-*` GenerateContent for `source.ip` and `client.user.email`
44 in the same window to identify the caller.
45- Look for related alerts (jailbreak heuristics, repeated refusals, BLOCK_NONE) from the same
46 project/model.
47
48### False positive analysis
49
50- Authorized red-team or content-moderation workloads that intentionally score MEDIUM/HIGH.
51 Exclude those projects or principals.
52- Borderline creative-writing or news-summarization prompts can occasionally score MEDIUM — read
53 the prompt before escalating.
54
55### Response and remediation
56
57- If the prompt is malicious and unauthorized: quarantine the calling identity, revoke Vertex
58 credentials, and review IAM.
59- If `BLOCK_NONE` was used, require stricter thresholds (for example BLOCK_MEDIUM_AND_ABOVE) via
60 org policy or application defaults.
61"""
62references = [
63 "https://www.elastic.co/docs/reference/integrations/gcp_vertexai",
64 "https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/configure-safety-filters",
65]
66risk_score = 47
67rule_id = "83ac492d-d5b5-4db6-89d4-d1be7456c54c"
68setup = """## Setup
69
70Requires prompt_response_logs with candidates.safety_ratings.* populated. Ratings appear when the client sends
71safetySettings on the GenerateContent request.
72"""
73severity = "medium"
74tags = [
75 "Domain: GenAI",
76 "Domain: Cloud",
77 "Data Source: GCP Vertex AI",
78 "Data Source: GCP",
79 "Data Source: Google Cloud Platform",
80 "Platform: GCP",
81 "Service: GCP Vertex AI",
82 "Use Case: Policy Violation",
83 "Use Case: Threat Detection",
84 "Tactic: Defense Evasion",
85 "Threat: Unauthorized AI Usage",
86 "Resources: Investigation Guide",
87 "Rule Type: ES|QL",
88]
89timestamp_override = "event.ingested"
90type = "esql"
91
92query = '''
93from logs-gcp_vertexai.prompt_response_logs-* metadata _id, _version, _index
94| where
95 data_stream.dataset == "gcp_vertexai.prompt_response_logs" and
96 (
97 MV_CONTAINS(gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.probability, "HIGH") or
98 MV_CONTAINS(gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.probability, "MEDIUM")
99 )
100| keep
101 _id,
102 _version,
103 _index,
104 @timestamp,
105 cloud.project.id,
106 gcp.vertexai.prompt_response_logs.model,
107 gcp.vertexai.prompt_response_logs.api_method,
108 gcp.vertexai.prompt_response_logs.full_request.contents.parts.text,
109 gcp.vertexai.prompt_response_logs.full_request.safety_settings.threshold,
110 gcp.vertexai.prompt_response_logs.full_response.candidates.finish_reason,
111 gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.category,
112 gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.probability,
113 gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.severity
114'''
115
116[[rule.threat_mappings]]
117framework = "MITRE ATLAS"
118version = "2026.08"
119[[rule.threat_mappings.threat]]
120framework = "MITRE ATLAS"
121
122[rule.threat_mappings.threat.tactic]
123id = "AML.TA0007"
124name = "Defense Evasion"
125reference = "https://atlas.mitre.org/tactics/AML.TA0007/"
126
127[rule.investigation_fields]
128field_names = [
129 "cloud.project.id",
130 "gcp.vertexai.prompt_response_logs.model",
131 "gcp.vertexai.prompt_response_logs.api_method",
132 "gcp.vertexai.prompt_response_logs.full_request.contents.parts.text",
133 "gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.category",
134 "gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.probability",
135 "gcp.vertexai.prompt_response_logs.full_response.candidates.safety_ratings.severity",
136 "gcp.vertexai.prompt_response_logs.full_response.candidates.finish_reason",
137 "gcp.vertexai.prompt_response_logs.full_request.safety_settings.threshold",
138]
Triage and analysis
Investigating GCP Vertex AI Elevated Safety Rating on Response
A GenerateContent response included safety_ratings.probability of HIGH or MEDIUM for one or more
Gemini harm categories (for example HARM_CATEGORY_HATE_SPEECH or
HARM_CATEGORY_DANGEROUS_CONTENT). That is a stronger signal than NEGLIGIBLE/LOW and often means
the prompt probed disallowed content — whether or not generation was fully blocked.
Possible investigation steps
- Read the prompt in
gcp.vertexai.prompt_response_logs.full_request.contents.parts.text. - Note
safety_ratings.category,probability, andseverityon the alert, plusfinish_reason.SAFETYwith HIGH/MEDIUM is high confidence;STOPwith HIGH still warrants review of what was returned. - Check
full_request.safety_settings.thresholdon the same event.BLOCK_NONEmeans category blocking was disabled for listed categories. - Pivot to
logs-gcp_vertexai.auditlogs-*GenerateContent forsource.ipandclient.user.emailin the same window to identify the caller. - Look for related alerts (jailbreak heuristics, repeated refusals, BLOCK_NONE) from the same project/model.
False positive analysis
- Authorized red-team or content-moderation workloads that intentionally score MEDIUM/HIGH. Exclude those projects or principals.
- Borderline creative-writing or news-summarization prompts can occasionally score MEDIUM — read the prompt before escalating.
Response and remediation
- If the prompt is malicious and unauthorized: quarantine the calling identity, revoke Vertex credentials, and review IAM.
- If
BLOCK_NONEwas used, require stricter thresholds (for example BLOCK_MEDIUM_AND_ABOVE) via org policy or application defaults.
References
Related rules
- GCP Vertex AI Repeated Assistant Refusals
- GCP Vertex AI Response Blocked by Safety Filters
- GCP Vertex AI Jailbreak Prompt Heuristics
- GCP Vertex AI Publisher Model Config Modified
- GCP Vertex AI Safety Filters Set to BLOCK_NONE