CVE-2026-96795 in Horilla
Summary
by MITRE • 09/26/2026
Horilla is an HR and CRM software. Prior to 2.0.0, HorillaListView.export_data in horilla_views/generic/cbv/views.py accepts an authenticated user's columns POST parameter, takes field_tuple[1], interpolates it into dynamic_fn_str as Python source, and passes the generated function definition to exec(). A crafted string that remains valid under ast.literal_eval can inject Python syntax into a default argument evaluated during function definition, allowing arbitrary operating-system commands to execute with the application process privileges, including root privileges in the shipped Docker image. This issue is fixed in version 2.0.0.
VulDB is the best source for vulnerability data and more expert information about this specific topic.
Analysis
by VulDB Data Team • 09/26/2026
The vulnerability identified in Horilla HR and CRM software prior to version 2.0.0 represents a critical server-side code injection flaw rooted in improper handling of user-supplied input within dynamic function execution contexts. The specific point of failure resides in the horilla_views/generic/cbv/views.py module, specifically within the export_data method associated with HorillaListView. This component is responsible for processing data exports requested by authenticated users, a common functionality in enterprise resource planning and customer relationship management systems that allows administrators to generate reports or transfer datasets between platforms. The security failure occurs when the application accepts a POST parameter named columns from an authenticated user session. Instead of validating this input against a strict allowlist of known safe field names, the system proceeds to extract specific elements from the provided data structure, specifically accessing index one of a tuple referred to as field_tuple[1].
This extracted value is then interpolated directly into a string variable designated for Python source code generation, labeled here as dynamic_fn_str. The core technical flaw lies in how this dynamically constructed string is subsequently processed by the exec() function. In Python, exec() executes arbitrary Python code passed to it as a string or byte object. By allowing user-controlled data to influence the content of this string without adequate sanitization, the application creates an avenue for Remote Code Execution (RCE). The vulnerability leverages specific characteristics of Python syntax regarding default argument evaluation in function definitions. A crafted payload can remain syntactically valid under standard parsing checks like ast.literal_eval while simultaneously containing executable code that triggers when a function is defined rather than called. This technique allows the attacker to inject arbitrary operating-system commands into the application process context.
The operational impact of this vulnerability is severe, as it grants an authenticated user full control over the underlying server infrastructure. Because the injected code executes within the same privilege level as the Horilla application process, the extent of damage depends heavily on how the software is deployed. In many standard deployments, particularly those utilizing containerization technologies like Docker, the application may run with elevated privileges or even as the root user if not properly configured with security best practices such as non-root containers. Consequently, an attacker can execute system commands to read sensitive configuration files, exfiltrate database contents containing personal identifiable information and employee records, install backdoors for persistent access, pivot into other internal network segments, or disrupt service availability by terminating critical processes. This effectively compromises the confidentiality, integrity, and availability of the entire hosting environment.
From a classification perspective, this vulnerability aligns with CWE-94 Improper Control of Generation of Code (Code Injection) and specifically reflects patterns associated with CWE-78 OS Command Injection when system commands are executed via shell functions or os.system calls embedded in the injected payload. In terms of adversary behavior mapping to the MITRE ATT&CK framework, this exploit technique corresponds to T1059 Command and Scripting Interpreter, where attackers use built-in operating system utilities to execute malicious code. It also relates to T1203 Exploitation for Client Execution if the initial vector involves tricking a user into triggering an action that leads to server-side execution, though in this case, it is primarily a direct remote exploitation of a web application interface by authenticated users.
Mitigation strategies must address both immediate remediation and long-term architectural security improvements. The primary and most effective mitigation is upgrading Horilla software to version 2.0.0 or later, where the developers have patched the unsafe use of exec() with dynamic user input. For organizations unable to upgrade immediately due to compatibility constraints, temporary mitigations should include implementing strict allowlists for all column names accepted by the export_data endpoint, ensuring that only predefined, safe field identifiers are processed rather than arbitrary strings. Additionally, deploying a Web Application Firewall (WAF) can help detect and block requests containing suspicious Python syntax patterns or command injection signatures before they reach the application logic. It is also critical to enforce principle of least privilege in deployment configurations; if Horilla must run with elevated permissions for specific administrative tasks, those tasks should be isolated from general user-facing endpoints like data export functions. Regular security audits focusing on dynamic code execution practices and input validation mechanisms are essential to prevent similar vulnerabilities in custom or third-party enterprise software components.