The go-to resource for upgrading Ruby, Rails, and your dependencies.

How to Fix Active Support File Disclosure (CVE-2023-38037) in Rails 7


During World War II, when Allied codebreakers at Bletchley Park decrypted Enigma intercepts, the decoded messages were strictly controlled. The act of decrypting a message temporarily exposed its contents in plaintext; if a clerk had left a decoded message lying on a desk in a shared room, the strength of the original encryption would have been rendered pointless.

Similarly, when we edit encrypted secrets in a Ruby on Rails application, the framework must temporarily expose them in plaintext so our editor can read them. If we aren’t careful about where and how this temporary plaintext is stored, we risk exposing our application’s most sensitive data to anyone else on the system.

This brings us to a local file disclosure vulnerability — designated as CVE-2023-38037 — that was identified in the ActiveSupport::EncryptedFile component of the Rails framework. This vulnerability affects how Rails handles encrypted credentials and secrets during the editing process.

Before we get into the technical resolution, though, we should examine exactly how this exposure happens. When we use commands like bin/rails credentials:edit to modify encrypted files, Active Support temporarily decrypts the contents and writes them to a temporary file on the local filesystem. Historically, the permissions for this temporary file were dictated by the user’s active umask settings. If the environment’s umask was overly permissive, other users on the same system could potentially read the decrypted secrets while the file was open in our editor.

For environments with shared access — such as multi-tenant CI/CD runners, shared staging servers, or development workstations — this presents a significant risk. An attacker with local filesystem access could potentially capture several types of sensitive data:

  • Production database credentials
  • Third-party API keys
  • Application encryption secrets
  • Other sensitive environmental configuration

Diagnosing Your Application’s Exposure

To determine if our application is vulnerable to CVE-2023-38037, we must audit our Rails and Active Support versions.

We should specifically look for the following vulnerable versions:

  • Rails and Active Support versions prior to 7.0.7
  • Rails and Active Support versions prior to 6.1.7.5

We can check our exact Active Support version by running the bundle info command, which queries our local environment for the version and description of a loaded gem:

$ bundle info activesupport
  * activesupport (7.0.6)
	Summary: A toolkit of support libraries and Ruby core extensions extracted from the Rails framework.

I’ve abbreviated the above output for the sake of brevity; the remaining text contains the path on the filesystem where the gem is installed.

If our application uses Rails versions prior to 7.0.7 or 6.1.7.5, we are likely exposed to this vulnerability when editing encrypted files. It is also worth checking our Gemfile.lock directly to confirm the exact patch level running in our production and development environments. The Gemfile.lock records the exact versions of all gems actually installed, including their transitive dependencies, whereas the Gemfile typically only specifies our broad version requirements.

How Umask Contributes to the Problem

One may wonder: if ActiveSupport is creating the file, why does the operating system allow other users to read it? The answer is straightforward, and it has to do with how Unix-like operating systems handle file creation.

By way of a memory aide, you can think of umask (user file-creation mode mask) as a filter that subtracts permissions from newly created files. When a program asks the operating system to create a file, it asks for certain default permissions (often 0666, meaning read and write access for everyone). The umask then “masks out” or removes permissions based on its value.

Let’s illustrate that with a quick shell experiment:

$ umask
0022
$ touch test_secret.txt
$ ls -l test_secret.txt
-rw-r--r--  1 user  staff  0 Mar 16 10:00 test_secret.txt

We can notice a few things here. Because our umask was 0022, it removed write permissions for the “group” and “others”, but it left read permissions intact (-rw-r--r--). If Active Support created a temporary file containing our decrypted secrets with this umask, any other user on the machine could cat the file and read our production database password!

Applying the Security Patch

The most direct and permanent solution is to update our Rails dependencies to a secure version. The Rails core team released patches that force strict file permissions (specifically 0600) on the temporary files generated by ActiveSupport::EncryptedFile, regardless of the system’s umask.

This means that, strictly speaking, the file will only be readable and writable by the user who created it. The patch forces the file creation mode to 0600 directly at the system call level, overriding whatever default mask the shell environment attempts to apply.

Updating Your Gemfile

For applications on supported framework versions, updating the dependency is a straightforward process. We will need to bump the Rails and Active Support gems in our Gemfile:

# For Rails 7.0 applications
gem 'rails', '~> 7.0.7'

# For Rails 6.1 applications
gem 'rails', '~> 6.1.7.5'

After modifying the Gemfile, we generate a new lockfile and verify the update. We specifically update both activesupport and rails simultaneously, as they are tightly coupled and updating only one can cause dependency resolution conflicts:

$ bundle update activesupport rails
Installing activesupport 7.0.7 (was 7.0.6)
Bundle updated!

Again, I’ve abbreviated the bundle output for the sake of brevity; the omitted lines list the other gems that were evaluated or installed during the dependency resolution.

Verifying the Patch

Once the dependencies are updated, we should run our application’s test suite to ensure the minor version bump introduces no regressions in our specific codebase:

$ bundle exec rspec

Implementing Temporary Workarounds

Of course, immediate upgrades are not always feasible for complex, legacy applications. If you are operating an older Rails version and cannot immediately patch the framework, you can mitigate the risk by strictly controlling the umask before invoking the credential editor.

Before running the credentials edit command, you can temporarily set your umask to 0077. This ensures that any files created by your user account are readable and writable only by you:

$ umask 0077
$ bin/rails credentials:edit

Let’s verify that this read-only approach works. If we create a file with this new umask:

$ touch test_secure_secret.txt
$ ls -l test_secure_secret.txt
-rw-------  1 user  staff  0 Mar 16 10:05 test_secure_secret.txt

As we can see, running the touch command now creates a file that is entirely inaccessible to other users (-rw-------).

While this prevents the specific file disclosure vector, relying on manual operational procedures is fragile. If a developer forgets to set the umask on a shared system, the temporary file is exposed. Therefore, although implementing a workaround prevents future exposure, any currently exposed production credentials should be immediately rotated—if your system was shared with untrusted users, one must assume they are compromised.

The Long-Term Solution: Sustainability

Addressing CVE-2023-38037 through manual workarounds or isolated patches treats the symptom rather than the underlying disease. As Rails applications age, they accumulate technical debt that makes applying security patches increasingly difficult. When a framework version reaches End-of-Life (EOL), it no longer receives these critical security backports.

If our application is stuck on an outdated version of Rails, though, we are likely exposed to numerous other vulnerabilities beyond ActiveSupport::EncryptedFile. To maintain a secure and sustainable codebase, we must consider the long-term implications of our technical decisions. By systematically upgrading Ruby and Rails to current, supported versions, we ensure ongoing access to security patches, performance improvements, and modern developer tooling.

This approach eliminates the technical debt hotspots that make security patching so painful in the first place, aligning with the philosophy of building durable, maintainable software.

Sponsored by Durable Programming

Need help maintaining or upgrading your Ruby on Rails application? Durable Programming specializes in keeping Rails apps secure, performant, and up-to-date.

Hire Durable Programming