Skip to content
16

16

github.com • September 20, 2026

During a security audit conducted on 2026-07-09 , 7 critical security vulnerabilities were identified in SxDevOps (main branch). These vulnerabilities range from Remote Code Execution (RCE) to privilege escalation and hardcoded credentials. This Issue reports all findings to the project maintainer as per the project's SECURITY.md policy.

Affected Version: v1.1 (Latest)

Vulnerability Overview

V-01: MCP STDIO Command Injection (RCE)

CWE: CWE-78 (OS Command Injection) CVSS 3.1: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (9.8 Critical) Affected File: backend/aiops/services.py , lines ~14159-14178 Authentication Required: Yes (low-privilege user with aiops.mcp.manage permission)

The MCP (Model Context Protocol) server management feature allows authenticated users to create MCP servers of type stdio . The endpoint_or_command field is passed directly to subprocess.Popen() via shlex.split() without any validation or sanitization. When the MCP session is initialized (via test_connection API), the injected command is executed on the backend server with the privileges of the Django application process.

Additionally, the auth_config.env field allows setting arbitrary environment variables (including dangerous ones like LD_PRELOAD , PATH , PYTHONPATH ), further expanding the attack surface.

Vulnerable Code Pattern

Remote Code Execution on the backend server with Django process privileges

In observed deployment, execution as Windows Administrator account

Full credential extraction (SSH passwords stored in plaintext, API keys)

Lateral movement to all managed hosts via stored SSH credentials

Whitelist executables : Restrict endpoint_or_command to pre-approved executable paths; reject values containing shell metacharacters

Filter dangerous environment variables : Block LD_PRELOAD , PATH , PYTHONPATH , DYLD_INSERT_LIBRARIES in auth_config.env

Sandbox MCP processes : Run MCP STDIO subprocesses in an isolated container with minimal privileges

V-02: SSH exec_command Unfiltered Command Injection (Host RCE)

CWE: CWE-78 (OS Command Injection) CVSS 3.1: AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H (9.8 Critical) Affected File: backend/ops/host_tasks.py , lines ~293, 589 Authentication Required: Yes (user with ops.task.execute permission)

The TASK_RUN_COMMAND task type passes payload.command directly to paramiko.SSHClient.exec_command() without any filtering or escaping. While the TASK_SERVICE_STATUS branch uses shlex.quote() for sanitization, the TASK_RUN_COMMAND branch has zero filtering. An attacker can chain arbitrary commands using ; , && , || to execute them on target hosts.

Vulnerable Code Pattern

RCE on all SSH-managed hosts with the SSH user's privileges

Lateral movement from the SxDevOps server to all managed infrastructure

Full data access on all managed hosts

Apply shlex.quote() to payload.command before exec_command() , consistent with the TASK_SERVICE_STATUS branch

Implement a command whitelist/blacklist to block dangerous patterns ( rm -rf , curl|bash , reverse shells)

Require secondary confirmation for high-risk commands

V-03: LLM-Generated Shell Commands Enter Task Drafts Without Validation

CWE: CWE-78 (OS Command Injection) CVSS 3.1: AV:N/AC:L/PR:L/UI:R/S:C/C:H/I:H/A:H (9.1 Critical) Affected File: backend/aiops/services.py , lines ~12280-12379, 12765-12827 Authentication Required: Yes (user with AIOps chat access) User Interaction: Required (user confirms task draft)

The generate_host_task tool accepts a command parameter that comes directly from the LLM's tool call output. This value is passed into build_task_draft() without any validation against DANGEROUS_COMMAND_PATTERNS — a list that already exists in the codebase (containing rm -rf , shutdown , reboot , etc.) but is only applied to MCP output sanitization, never to task draft creation.

This creates an attack vector through prompt injection: an attacker can craft a chat message that causes the LLM to generate malicious commands, which then appear as legitimate task drafts awaiting user confirmation.

Vulnerable Code Pattern

Execution of destructive commands : LLM hallucination or prompt injection can produce rm -rf / , reverse shells, etc.

Social engineering amplification : Task drafts from the AI assistant carry implicit trust

Automation risk : The auto-materialize code path (currently disabled but fully implemented) would eliminate human confirmation

Apply DANGEROUS_COMMAND_PATTERNS validation in build_task_draft() — reject or flag matching commands

Highlight the full command text in the task confirmation UI for user review

If auto-materialize is not planned, remove the code path entirely

V-04: UserSerializer Allows Writing is_superuser/is_staff (Privilege Escalation)

CWE: CWE-266 (Incorrect Privilege Assignment) CVSS 3.1: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H (8.8 Critical) Affected File: backend/rbac/serializers.py , lines ~122-164 Authentication Required: Yes (user with rbac.user.manage permission)

UserSerializer includes is_superuser , is_staff , and is_active in its Meta.fields , but read_only_fields only protects date_joined and last_login . The update() method iterates over all validated_data fields and applies them via setattr() , meaning any user with rbac.user.manage permission can set is_superuser=True on any account — including their own — bypassing the entire RBAC permission system.

Vulnerable Code Pattern

Complete RBAC bypass : The entire permission system is undermined

Persistence : Attacker can create backdoor superuser accounts

Full system control : Superusers can access all API endpoints, manage all hosts, execute arbitrary commands

Add is_superuser , is_staff , and is_active to read_only_fields

If these fields need modification, create a separate restricted API with audit logging and secondary admin confirmation

Implement field-level permission checks — only existing superusers should grant superuser status

V-05: Hardcoded Default Superadmin Password admin/Admin@123456

CWE: CWE-798 (Use of Hard-coded Credentials) CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (9.8 Critical) Affected Files: backend/rbac/services.py (lines ~11-12), frontend/src/views/Login.vue (lines ~95, 120-122) Authentication Required: None (credentials are publicly visible)

SxDevOps contains a hardcoded default superadmin password Admin@123456 in two locations:

Backend : rbac/services.py defines DEFAULT_ADMIN_PASSWORD = 'Admin@123456' and the ensure_default_superuser() function creates a superadmin account with this password on first startup.

Backend : rbac/services.py defines DEFAULT_ADMIN_PASSWORD = 'Admin@123456' and the ensure_default_superuser() function creates a superadmin account with this password on first startup.

Frontend : Login.vue displays the default credentials on the login page and pre-fills the login form with admin / Admin@123456 .

Frontend : Login.vue displays the default credentials on the login page and pre-fills the login form with admin / Admin@123456 .

While the README documents these as demo accounts, the default behavior creates the account without forcing a password change, meaning any unmodified deployment is fully accessible to anyone who visits the login page.

Vulnerable Code Pattern

Trivial initial access : Any visitor to the login page obtains superadmin credentials

Cascading RCE : Combined with V-01, enables server-level code execution without technical exploitation

No security boundary : The platform provides no protection if the default password is not changed

Remove the credential display and pre-fill from the frontend login page

Force password change on first login after initial setup

Refuse to start the production server if the default admin password has not been changed

Generate a random admin password during first startup and log it once

V-06: Django SECRET_KEY Hardcoded with django-insecure- Prefix

CWE: CWE-798 (Use of Hard-coded Credentials) CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (9.1 Critical) Affected File: backend/sxdevops/settings.py , lines ~341-344 Authentication Required: None

SxDevOps hardcodes a Django SECRET_KEY fallback value in sxdevops/settings.py . The key uses the django-insecure- prefix, which Django itself flags as insecure, yet it is used as a fallback when the SECRET_KEY environment variable is not set (the default behavior).

Vulnerable Code Pattern

If the SECRET_KEY environment variable is not configured (the default), this known hardcoded value is used.

With a known SECRET_KEY , attackers can:

Forge signed Django session cookies — assume the identity of any user (including superadmin)

Bypass CSRF protection — generate valid CSRF tokens

Generate valid password reset tokens for any account

Sign arbitrary data that the application trusts

Remove the hardcoded fallback value; raise an exception if SECRET_KEY is not set via environment variable

Generate a cryptographically random SECRET_KEY during deployment

Store in a secret management service (e.g., HashiCorp Vault, AWS Secrets Manager)

Rotate the SECRET_KEY immediately if the current value has been exposed

V-07: DEBUG Mode Defaults to True

CWE: CWE-489 (Active Debug Code) CVSS 3.1: AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N (9.1 Critical) Affected File: backend/sxdevops/settings.py , line ~347 Authentication Required: None

SxDevOps sets DEBUG = True as the default value when the DEBUG environment variable is not configured. If the deployment omits this configuration (common for Docker-based deployments), the application runs in debug mode in production.

Vulnerable Code Pattern

In Django, DEBUG = True causes:

Detailed error pages on 500 errors — exposes full stack traces, local variables, SQL queries, and all settings values (including SECRET_KEY and database credentials)

Static file serving through Django (bypassing secure CDN configurations)

Enhanced logging that may include sensitive data

This vulnerability amplifies V-06: the exposed SECRET_KEY on a debug error page enables session forgery attacks.

Change the default value to False : DEBUG = _bool_value(os.getenv("DEBUG"), False)

Add a startup check that refuses to run in production if DEBUG = True

Document the requirement to explicitly set DEBUG=False in deployment guides

Additional References

Detailed advisory writeups are available in the reporter's advisory repository.

Advisory Repository: