Aug 25, 2026·6 min read·1 visit
An authenticated administrator in 3X-UI versions prior to 3.3.1 can perform remote code execution with root privileges by manipulating Xray log file paths to target host files like authorized_keys.
MHSanaei 3X-UI is a web control panel for managing Xray-core servers. In versions prior to 3.3.1, an authenticated administrator can abuse database import functions or raw template config fields to overwrite or append to arbitrary files on the host filesystem. This is achieved by altering the Xray log configuration variables to target system files, leveraging logging components to inject payloads.
3X-UI is a web-based administration panel designed to manage protocols and configurations for Xray-core proxies. The platform exposes a management interface that allows administrators to define users, control ports, modify operational logs, and import pre-configured SQLite database files.
This architecture creates an attack surface if input verification mechanisms fail to restrict administrative modifications of critical backend files. In versions prior to 3.3.1, the application allows administrative users to write arbitrary data to unauthorized system locations by exploiting configuration options associated with the logging path parameters.
The specific vulnerability class is CWE-73: External Control of File Name or Path. Under specific deployment contexts, this behavior allows remote attackers with administrative credentials to execute arbitrary commands as the user executing the Xray daemon process, which frequently defaults to the root user.
The vulnerability stems from an inadequate validation routine within the log path resolution functionality implemented in the Go backend. When preparing configuration settings for execution by the underlying Xray daemon, the application processes log storage paths defined by parameters log.access and log.error.
Prior to version 3.3.1, the path validation relies on the resolveXrayLogPaths function located in the source file internal/web/service/xray.go. This function validates paths using Go's standard library check filepath.IsAbs(). If the validation check determines that a specified path is absolute, it returns early and allows the configured path to be utilized directly by the Xray configuration exporter.
This logic is flawed because it assumes that any user-submitted absolute path is safe and authorized for write operations. Because Xray is often deployed with highly elevated system privileges, the application-level logic fails to establish a secure sandbox boundary, letting the Xray daemon write logging outputs to system-sensitive files like /root/.ssh/authorized_keys or directory-specific execution logs.
An inspection of the vulnerable implementation in internal/web/service/xray.go demonstrates the precise logical error. The function resolveXrayLogPaths iterates over user-controlled paths but bypasses processing when meeting an absolute path identifier.
// Vulnerable path validation loop in internal/web/service/xray.go
func resolveXrayLogPaths(logCfg json_util.RawMessage) json_util.RawMessage {
// ...
for key, trimmed := range parsed {
if trimmed == "" || strings.EqualFold(trimmed, "none") {
continue
}
if filepath.IsAbs(trimmed) {
// Bypasses path correction if the input path is absolute.
// This allows the configuration to use arbitrary targets on the host filesystem.
continue
}
// ...
}
// ...
}The remediation commit 80e168787ed608e83a065033ee94c8bfc3025ce7 corrects this behavior by stripping directory information and confining the resulting base filename within the established log folder.
// Patched implementation in internal/web/service/xray.go
func resolveXrayLogPaths(logCfg json_util.RawMessage) json_util.RawMessage {
if len(logCfg) == 0 {
return logCfg
}
// ...
for key, value := range parsed {
trimmed := strings.TrimSpace(value)
if trimmed == "" || strings.EqualFold(trimmed, "none") {
continue
}
// Convert all paths to use standard forward slashes to prevent platform evasion
base := path.Base(filepath.ToSlash(trimmed))
if base == "" || base == "." || base == ".." || base == "/" {
continue
}
// Force confinement into the designated system logging directory
confined := filepath.Join(config.GetLogFolder(), base)
if confined == trimmed {
continue
}
parsed[key] = confined
changed = true
}
// ...
}The security fix replaces vulnerable pass-through behavior with strict validation. It normalizes paths to generic forward slashes using filepath.ToSlash() and then extracts the file's base name via path.Base(). The resulting string is explicitly combined with the authorized base directory returned by config.GetLogFolder(), blocking path traversal or absolute file path overrides.
To execute this attack, an actor must possess active administrative session cookies on the target 3X-UI application portal. This access is obtained through credential abuse, brute-force attacks, or session hijacking.
The attack sequence begins with the generation of a malicious SQLite database file. The attacker modifies the configuration values log.access or log.error in the settings database table, updating the path to direct log data into target configuration scripts, system directories, or credential databases on the host system.
The attacker then utilizes the database import feature to upload the modified file to the active 3X-UI panel. Once imported, the panel recreates the configuration template files used to control the Xray daemon. The target destination is now bound to the log writer.
To achieve persistent remote execution, the attacker registers a client inbound entry containing their public key string in the connection email field. When the attacker initiates a connection to the proxy port, the Xray process logs the connection attempt, writing the credential payload directly to the user-supplied path. The next SSH session launched with the matching private key establishes a remote shell context.
Successful exploitation of CVE-2026-55477 leads to immediate unauthorized file manipulation with the privileges of the Xray-core process. Because standard installations run the daemon process under the root account, the integrity of the host operating system can be fully compromised.
The severity of this issue is evaluated with a CVSS v3.1 score of 7.2 (High). The metric breakdown reflects high confidentiality, integrity, and availability impacts (C:H/I:H/A:H). However, the exploit path requires prior administrative privilege on the application panel (PR:H), reducing the base scoring compared to unauthenticated remote code execution chains.
The potential consequences extend beyond standard log file pollution. By appending commands to files in system startup paths, user profiles, or cron configuration templates, attackers can pivot from administrative control of the proxy panel to comprehensive, persistent root-level control of the underlying Linux host.
Remediation requires upgrading the 3X-UI installation to version 3.3.1 or higher. This release integrates secure path confinement code, which automatically normalizes input configurations and blocks absolute paths.
If an immediate system upgrade is not viable, the following defensive configurations must be implemented to reduce the active attack surface:
SELECT * FROM settings WHERE key LIKE '%log%';Additionally, security teams should implement logging and host monitoring solutions. System auditing frameworks must actively watch for unexpected write activity targeting /root/.ssh/ or standard scheduled task paths.
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H| Attribute | Detail |
|---|---|
| CWE ID | CWE-73 (External Control of File Name or Path) |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.2 |
| EPSS Score | 0.00615 (Percentile: 46.77%) |
| Exploit Status | PoC / Conceptual |
| CISA KEV Status | Not Listed |
A security vulnerability in the github.com/gorilla/websocket Go library allows remote attackers to predict client-to-server frame masking keys. This occurs because the library generates 32-bit mask keys using Go's non-cryptographically secure pseudo-random number generator (math/rand). Predicting these keys enables adversaries to bypass proxy-based security protections, facilitating HTTP request smuggling and cache poisoning attacks.
Cloudreve is vulnerable to an incorrect authorization bypass. When listing files, Cloudreve returns a context_hint (represented as a UUID) to the client. If this context hint is replayed on the /file/url or /file/thumb routes, Cloudreve's database file system caches the shareNavigatorState containing the loaded share root. Within the cache lifetime (TTL of 300 seconds), if the user re-requests the same file with the cached hint, the system restores the state and completely bypasses the root security checks (which validate share expiration, remaining download limits, owner status, and passwords). This allows unauthorized users to continue generating signed file URLs and downloading files even after a share has been deleted, has expired, or has reached its download limit.
A path traversal vulnerability exists in Cloudreve's remote download workflow, where improper sanitization of file paths returned by configured remote downloaders (such as aria2) allows authenticated users to write files outside the designated target folder.
An integer overflow vulnerability exists in the HTTP/1.x chunked encoding parser of the vibeio-http library. The flaw is caused by unchecked integer addition when calculating the total buffer size required for processing parsed chunk lengths. By sending a maliciously crafted HTTP request containing an extremely large chunk size, an unauthenticated remote attacker can trigger a runtime panic, leading to complete denial of service.
netfoil, an allowlist-based DNS proxy, failed to sanitize ALPN fields parsed from untrusted DNS-over-HTTPS (DoH) HTTPS Resource Records. This allowed attackers to inject ANSI escape sequences into log files or trigger Denial of Service (DoS) via uncontrolled memory allocations.
An issue was discovered in the tokio-postgres library for Rust prior to version 0.7.18. A trust assumption mismatch between the PostgreSQL protocol messages sent by a server and how they are parsed and indexed by the client-side library allows a rogue or compromised database server to trigger a Denial of Service (DoS) crash via an unhandled out-of-bounds slice indexing panic.