Feb 27, 2026·5 min read·91 visits
Improper path sanitization in the Vitess backup restore process allows attackers with backup storage access to write arbitrary files to the host OS via manipulated manifests.
A critical path traversal vulnerability exists in the Vitess `builtinbackupengine` component, specifically within the backup restoration workflow. The flaw arises from improper validation of file paths defined in the backup `MANIFEST` file. An attacker with write access to the backup storage location (e.g., S3, GCS, or NFS) can craft a malicious backup manifest containing directory traversal sequences. When a Vitess `vttablet` attempts to restore from this compromised backup, the system processes these sequences, allowing arbitrary file writes to the underlying host filesystem. This vulnerability permits attackers to break out of the intended data directory, potentially overwriting system binaries, configuration files, or authorized keys to achieve remote code execution.
Vitess is a database clustering system for horizontal scaling of MySQL. A core component of its reliability strategy is the backup and restore functionality managed by the builtinbackupengine. This engine handles the serialization of database states into storage backends (like AWS S3, Google Cloud Storage, or local mounts) and their subsequent restoration to vttablet instances.
The vulnerability, identified as CVE-2026-27969, resides in the logic responsible for interpreting the MANIFEST file during a restore operation. The MANIFEST is a metadata file that lists the objects contained within a backup and specifies where they should be placed on the local disk relative to the database root.
Due to a failure to sanitize the Name field within this manifest, the restoration process accepts relative path components (e.g., ../). This allows the restore routine to traverse outside the designated data directory. Consequently, the trust boundary is violated: the backup storage, which should only contain passive data, becomes a vector for active attacks against the database infrastructure.
The root cause of this vulnerability is the insecure usage of the path.Join function in Go when handling untrusted input from the backup manifest. The specific flaw is located in the fullPath method of the FileEntry structure within go/vt/mysqlctl/builtinbackupengine.go.
When Vitess performs a restore, it unmarshals the MANIFEST JSON file into FileEntry objects. Each entry contains a Name field representing the filename. The vulnerable code attempted to construct the absolute destination path by concatenating the base restore directory with this Name field using path.Join. While path.Join cleans paths by removing redundant separators, it does not prevent directory traversal if the resulting path is lexically valid.
Specifically, path.Join("/vt/data", "../../etc/passwd") resolves to /etc/passwd. The application failed to verify that the final resolved path remained rooted within the intended destination directory (e.g., /vt/data). This omission allows an attacker who controls the manifest to direct the file write operation to any location writable by the vttablet process.
The vulnerability exists in the fullPath method, which calculates where a file from the backup should be written. Below is the comparison between the vulnerable and patched implementations.
In the original code, the Name field (derived directly from the JSON manifest) is passed to path.Join without prior validation. If fe.Name contains ../, it alters the directory hierarchy of the result.
// go/vt/mysqlctl/builtinbackupengine.go
func (fe *FileEntry) fullPath(cnf *Mycnf) (string, error) {
// ... [root calculation logic] ...
// VULNERABLE: path.Join resolves "../" but does not sandbox the path.
// If fe.Name is "../../bin/malicious", the output escapes the root.
return path.Join(fe.ParentPath, root, fe.Name), nil
}The fix, introduced in commit c565cab615bc962bda061dcd645aa7506c59ca4a, replaces the standard path.Join with a proprietary fileutil.SafePathJoin. This utility function conceptually performs the join and then checks if the resulting path is a subdirectory of the intended base.
// go/vt/mysqlctl/builtinbackupengine.go
func (fe *FileEntry) fullPath(cnf *Mycnf) (string, error) {
// ... [root calculation logic] ...
// FIXED: SafePathJoin ensures the result is contained within the parent.
// Returns an error if the path attempts to traverse upwards.
return fileutil.SafePathJoin(path.Join(fe.ParentPath, root), fe.Name)
}The patch effectively enforces a jail on the file extraction process. Any attempt to supply a path containing traversal sequences that resolve outside the root will now trigger a fileutil.ErrInvalidJoinedPath error, aborting the write operation.
Exploitation of CVE-2026-27969 requires a specific position in the network topology: write access to the backup storage. This is classified as PR:H (Privileges Required: High) in CVSS 4.0, as backup locations are typically restricted. However, in compromised cloud environments or environments with overly permissive S3 bucket policies, this becomes a viable attack vector.
Attack Workflow:
MANIFEST file from the storage.MANIFEST JSON. They add a FileEntry where the Name attribute is set to a traversal path, such as ../../../../../../usr/local/bin/malicious_script, mapping it to the uploaded payload.vttablet initializes, it processes the manifest. The builtinbackupengine writes the payload to /usr/local/bin/malicious_script. The attacker then waits for the system or an administrator to execute the file, or overwrites a frequently executed cron job to gain immediate execution.> [!NOTE] > This attack is particularly dangerous in containerized environments (Kubernetes), where overwriting shared binaries or volume mounts can allow lateral movement to the host node.
The impact of this vulnerability is critical, principally affecting the Integrity and Confidentiality of the host system running the vttablet process. While the CVSS score is 9.3, the actual operational risk depends on the privileges of the Vitess process.
Direct Consequences:
.ssh/authorized_keys, or cron jobs, an attacker can elevate the arbitrary file write into full code execution.CVSS 4.0 Analysis:
The vector CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:P/VC:H/VI:H/VA:L/SC:L/SI:H/SA:H highlights that while high privileges (access to backups) are required, the subsequent impact on the vulnerable system (Confidentiality and Integrity) is High. The attack complexity is Low once access is obtained.
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:P/VC:H/VI:H/VA:L/SC:L/SI:H/SA:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Vitess vitessio | < 22.0.4 | 22.0.4 |
Vitess vitessio | >= 23.0.0, < 23.0.3 | 23.0.3 |
| Attribute | Detail |
|---|---|
| CWE | CWE-22 (Path Traversal) |
| CVSS v4.0 | 9.3 (Critical) |
| Attack Vector | Network (Backup Storage) |
| Exploit Maturity | None (No public PoC) |
| EPSS Score | 0.04% |
| Affected Component | builtinbackupengine |
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
A high-severity type-confusion vulnerability exists in NearForm fast-jwt prior to version 6.3.0. The vulnerability allows attackers to bypass crucial claim validation steps (such as expiration, issuer, audience, and subject validations) by presenting a validly signed JSON Web Token structured as a JSON array instead of a JSON object. This occurs because the library's decoder fails to reject JSON arrays during type evaluation.
NearForm fast-jwt prior to version 6.3.0 is vulnerable to an input validation flaw where configuring verifier properties (such as clockTolerance, clockTimestamp, and cacheTTL) with non-finite values like Infinity or NaN allows attackers to bypass temporal claim validations, including expiration (exp) and activation (nbf) boundaries. This validation bypass can result in unauthorized session persistence and cache poisoning.
A critical cryptographic vulnerability in fast-jwt versions 6.2.x prior to 6.3.0 allows unauthenticated remote attackers to execute an asymmetric-to-symmetric algorithm confusion attack due to incomplete validation of leading non-whitespace prefixes.
CVE-2026-107720 is a critical signature verification bypass vulnerability in NearForm's fast-jwt Node.js library. Under specific configurations where the token verifier is initialized with a falsy cryptographic key (such as an empty string or null) and a non-empty algorithms allowlist, the library erroneously skips signature validation. This allows unauthenticated remote attackers to submit fabricated, unsigned JSON Web Tokens and bypass the authorization boundary of the application entirely.
Ruby Mechanize prior to version 2.14.1 contains an information disclosure vulnerability. When executing cross-origin HTTP redirects, global headers configured on the Mechanize agent (such as Authorization or Session Cookies) are dynamically re-applied to the subsequent request, bypassing the internal header-stripping logic. An attacker who controls a redirection endpoint can capture sensitive bearer tokens or cookies.
An origin trust boundary failure in the Ruby mechanize library (prior to v2.14.1) allows unauthenticated remote web servers to harvest sensitive global request headers, such as Authorization Bearer tokens and cookies, by utilizing HTML-level meta-refresh redirection tags. Standard HTTP-level redirect boundaries were not applied to document-level redirects, creating a vector for cross-origin credential leakage during automated crawls.