Mar 24, 2026·6 min read·5 visits
A path traversal flaw in Rails Active Storage (CVSS 8.0) allows attackers to read or write arbitrary system files if the application permits user-defined blob keys. Patches are available in versions 7.2.3.1, 8.0.4.1, and 8.1.2.1.
Ruby on Rails Active Storage contains a path traversal vulnerability in the DiskService component. Applications allowing user-controllable keys expose arbitrary file read, write, and deletion capabilities to unauthenticated attackers due to inadequate path sanitization.
Ruby on Rails includes the Active Storage framework to manage file uploads and cloud storage attachments. The DiskService component handles local file storage by mapping a logical identifier, known as a blob key, to a physical file path on the host system. This mapping process relies on joining a configured storage root directory with the provided key.
CVE-2026-33195 identifies a path traversal vulnerability (CWE-22) within the DiskService implementation. The vulnerability arises because the framework fails to validate or sanitize the blob key before resolving the final absolute file path. Applications become vulnerable when they permit external users to define or heavily influence the key value during blob creation or retrieval operations.
An attacker exploiting this vulnerability can supply a key containing directory traversal sequences. This manipulation forces the application to resolve paths outside the intended storage sandbox. Depending on the application's implementation, this flaw exposes arbitrary file read, write, or deletion capabilities to the attacker.
The root cause of CVE-2026-33195 lies in the path_for method within ActiveStorage::Service::DiskService. Prior to the patched versions, this method constructed file paths using Ruby's File.join standard library function. The implementation combined the configured root path, an intermediate folder generated from the key, and the key itself.
Ruby's File.join function concatenates path segments using the system's directory separator but does not evaluate or collapse relative path sequences like ../. Consequently, passing a payload such as ../../etc/passwd directly into File.join results in a string that retains the traversal instructions. The operating system then processes these sequences during the subsequent file operation.
The vulnerable code lacked bounds checking to ensure the final resolved path remained a subdirectory of the intended storage root. Because the framework implicitly trusted the key parameter to be an alphanumeric identifier rather than a complex path, no sanitization layer intercepted the malicious payload. This design flaw created a direct conduit from user input to unauthorized file system access.
The vulnerable implementation of path_for consisted of a single line of code that joined the relevant path components. It performed no validation on the key parameter before returning the path string.
# Vulnerable implementation
def path_for(key)
File.join root, folder_for(key), key
endThe patched implementation replaces this single operation with a robust, multi-layered defense mechanism. The new code introduces syntactic validation to explicitly reject keys containing dot segments. It splits the key by the directory separator and checks for traversal indicators, raising an ActiveStorage::InvalidKeyError if any are detected. Additionally, it handles Encoding::CompatibilityError to prevent bypasses utilizing obscure text encodings.
# Patched implementation (Validation Layer)
begin
if key.split("/").intersect?(%w[. ..])
raise ActiveStorage::InvalidKeyError, "key has path traversal segments"
end
rescue Encoding::CompatibilityError
raise ActiveStorage::InvalidKeyError, "key has incompatible encoding"
endFollowing syntactic validation, the patch normalizes the path using File.expand_path and catches potential ArgumentError exceptions caused by null byte injections. Finally, the code applies prefix validation. It verifies that the fully expanded path strictly begins with the absolute path of the storage root, appended with a directory separator. This trailing slash prevents attacks targeting sibling directories.
# Patched implementation (Prefix Validation Layer)
unless path.start_with?(File.expand_path(root) + "/")
raise ActiveStorage::InvalidKeyError, "key is outside of disk service root"
endExploitation of CVE-2026-33195 requires the target application to accept user-controlled input for the Active Storage blob key. While standard Rails implementations typically generate random UUIDs for blob keys, custom direct upload endpoints or features utilizing manual Blob creation often allow clients to specify the key. In these configurations, the attack complexity is low and requires no authentication.
An attacker initiates the exploit by identifying a vulnerable endpoint that interacts with DiskService. The attacker constructs a malicious payload utilizing standard path traversal sequences, such as ../../../../etc/passwd, and submits it as the blob key parameter. The application processes this request and routes the payload to the path_for method.
Depending on the specific endpoint functionality, the attacker achieves different outcomes. A file retrieval endpoint allows the attacker to read arbitrary files from the host file system. A file upload or deletion endpoint permits the attacker to overwrite or remove system files, facilitating remote code execution or denial of service through file corruption.
CVE-2026-33195 carries a High severity rating with a CVSS v4.0 base score of 8.0. The vulnerability directly compromises the confidentiality and integrity of the underlying host system. The impact scope is restricted strictly to applications utilizing DiskService with user-controllable key parameters.
The confidentiality impact is High because an attacker can read sensitive configuration files, environment variables, or application source code. Accessing files like config/master.key or .env provides the attacker with database credentials and cryptographic secrets. This access typically facilitates secondary attacks against the application or connected infrastructure.
The integrity impact is also High due to the potential for arbitrary file writes or deletions. An attacker can overwrite executable code, configuration files, or authorized keys to establish persistence or escalate privileges. Despite these severe consequences, the availability metric is evaluated as None in the primary CVSS vector, though systemic deletion of critical files naturally degrades service availability.
The Rails core team addressed this vulnerability in versions 7.2.3.1, 8.0.4.1, and 8.1.2.1. Administrators must upgrade the activestorage gem to one of these patched releases immediately. Upgrading neutralizes the vulnerability by enforcing strict path resolution boundaries within the DiskService component.
If immediate upgrading is unfeasible, developers must implement custom validation logic at the application layer. Any endpoint accepting external input for blob keys must thoroughly sanitize the input. Developers should enforce strict regular expression matching to ensure the key contains only expected alphanumeric characters and does not include directory separators or dot segments.
Security teams should also review application code for custom ActiveStorage::Service implementations. Custom storage services derived from DiskService or implementing similar local file resolution logic may lack the newly introduced security controls. Auditing these implementations ensures comprehensive protection against path traversal vectors.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:U| Product | Affected Versions | Fixed Version |
|---|---|---|
activestorage rails | < 7.2.3.1 | 7.2.3.1 |
activestorage rails | >= 8.0.0.beta1, < 8.0.4.1 | 8.0.4.1 |
activestorage rails | >= 8.1.0.beta1, < 8.1.2.1 | 8.1.2.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Network |
| CVSS Score | 8.0 |
| Impact | Arbitrary File Read/Write/Delete |
| Exploit Status | Unweaponized |
| KEV Status | Not Listed |
The product does not properly neutralize special elements within the pathname that resolve to a location that is outside of the restricted directory.