CVE-2026-90774 Overview
CVE-2026-90774 is a path traversal vulnerability [CWE-22] in rustypaste, a self-hosted pastebin service written in Rust. Versions before 0.18.1 validate the destination path before applying the optional custom filename supplied via an HTTP header. Attackers can bypass the directory-escape check by placing path traversal sequences in the filename header. The result is an arbitrary file write outside the configured upload directory. Exploitation requires no authentication and can be performed remotely over the network.
Critical Impact
Unauthenticated remote attackers can write files to arbitrary locations on the host filesystem, enabling configuration tampering, web shell deployment, or overwriting of application binaries.
Affected Products
- rustypaste versions prior to 0.18.1
- Deployments exposing the rustypaste HTTP upload endpoint
- Self-hosted paste services built on the vulnerable paste.rs upload handler
Discovery Timeline
- 2026-09-13 - CVE-2026-90774 published to the National Vulnerability Database (NVD)
- 2026-09-14 - Last updated in NVD database
Technical Details for CVE-2026-90774
Vulnerability Analysis
The vulnerability resides in the file upload handler in src/paste.rs. When a client uploads a file, rustypaste first resolves and validates a destination path inside the configured upload directory. Only after this validation does the handler apply the optional filename HTTP header that lets clients override the stored filename.
The override is applied using path.set_file_name(file_name), which accepts arbitrary path components without re-checking that the resulting path remains inside the trusted base directory. A header value such as ../../etc/rustypaste_shell therefore escapes the sandbox after the safety check has already passed. Because the endpoint requires no authentication in default deployments, any network-reachable attacker can write attacker-controlled bytes to any filesystem location the rustypaste process can access.
Root Cause
The root cause is a classic time-of-check to time-of-use pattern combined with missing sanitization of client-supplied filenames. The safe_path_join helper in src/util.rs correctly enforces containment, but the header-driven override bypasses it entirely by mutating the already-validated PathBuf.
Attack Vector
An attacker sends an HTTP POST request to the rustypaste upload endpoint with a filename header containing traversal sequences. The server writes the request body to the attacker-chosen path relative to the upload directory. Overwriting rustypaste configuration files, systemd units, or dropping executables into web-served directories are realistic exploitation paths.
// Patch: src/paste.rs — route the override filename through safe_path_join
}
if let Some(header_filename) = header_filename {
file_name = header_filename;
- path.set_file_name(file_name);
+ path =
+ util::safe_path_join(self.type_.get_path(&config.server.upload_path)?, &file_name)?;
}
let file_name = path
.file_name()
Source: rustypaste commit ac05d55
// Patch: src/util.rs — hardened safe_path_join containment error handling
pub fn safe_path_join<B: AsRef<Path>, P: AsRef<Path>>(base: B, part: P) -> IoResult<PathBuf> {
- let new_path = base.as_ref().join(part).clean();
+ let new_path = base.as_ref().join(&part).clean();
let cleaned_base = base.as_ref().clean();
if !new_path.starts_with(cleaned_base) {
+ error!(
+ "{} is outside of {}",
+ part.as_ref().display(),
+ base.as_ref().display()
+ );
return Err(IoError::new(
IoErrorKind::InvalidData,
format!(
- "{} is outside of {}",
- new_path.display(),
- base.as_ref().display()
+ "{} is outside of the base directory",
+ part.as_ref().display()
),
));
}
Source: rustypaste commit ac05d55
Detection Methods for CVE-2026-90774
Indicators of Compromise
- HTTP requests to the rustypaste upload endpoint containing a filename header with ../, ..\, absolute paths, or URL-encoded traversal sequences.
- New or modified files under the rustypaste process working directory that fall outside the configured upload_path.
- rustypaste log entries containing is outside of the base directory after upgrading to 0.18.1, indicating attempted exploitation.
- Unexpected files with executable permissions in directories writable by the rustypaste service account.
Detection Strategies
- Inspect reverse-proxy and web server logs for POST requests to rustypaste with anomalous filename header values.
- Compare file inventory under and adjacent to the configured upload_path against a known-good baseline.
- Monitor process file writes by the rustypaste binary using OS-level auditing such as auditd file rules or eBPF file-write telemetry.
Monitoring Recommendations
- Enable verbose access logging on any reverse proxy fronting rustypaste and retain full HTTP header captures.
- Alert on write syscalls originating from the rustypaste process to paths outside the designated upload directory.
- Forward rustypaste and host filesystem events to a central data lake so header anomalies can be correlated with new file creations.
How to Mitigate CVE-2026-90774
Immediate Actions Required
- Upgrade rustypaste to version 0.18.1 or later on every host that exposes the service.
- Restrict network access to the rustypaste upload endpoint using firewall rules or an authenticating reverse proxy.
- Audit the filesystem for unexpected files created by the rustypaste service account since deployment.
- Rotate any credentials or tokens stored in files writable by the rustypaste process, in case they were overwritten or exfiltrated.
Patch Information
The fix was delivered in rustypaste 0.18.1 via commit ac05d552596af4a8429d80f30d11f67117ce02c8. The patch routes the client-supplied override filename through the safe_path_join helper so the final destination is re-validated against the trusted base directory. See the VulnCheck advisory for rustypaste and the rustypaste issue tracker for additional context.
Workarounds
- Place rustypaste behind a reverse proxy that strips or rejects requests containing a filename header with .., /, or \ characters.
- Run the rustypaste process as an unprivileged user inside a container or chroot with the upload directory mounted read-write and the rest of the filesystem read-only.
- Apply mandatory access controls such as AppArmor or SELinux policies limiting write access to the configured upload_path.
# Example: reject uploads with traversal sequences in the filename header (nginx)
map $http_filename $rustypaste_bad_filename {
default 0;
"~*(\.\./|\.\.\\|^/)" 1;
}
server {
location /upload {
if ($rustypaste_bad_filename) { return 400; }
proxy_pass http://127.0.0.1:8000;
}
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.