Information Disclosure via environment variable (DATABASE_URL) leakage in test environment

HIGH
rails/rails
Commit: 07f53df0a9b8
Affected: 8.1.x prior to this commit (pre-07f53df0a9b881ffc040fa57289b5e0316cc3d5d)
2026-04-05 12:54 UTC

Description

The commit prevents an information disclosure vulnerability where the Rails test suite could leak the DATABASE_URL environment variable. Previously, tests were setting ENV['DATABASE_URL'] globally, which could propagate to child processes or logging, exposing sensitive database configuration. The fix removes the global ENV manipulation and scopes the DATABASE_URL value within a controlled block using with_env, and it also removes reliance on a global config/database.yml in those tests. This ensures that DATABASE_URL is not unintentionally exposed during test execution.

Proof of Concept

Proof of concept (Ruby) demonstrating leakage before vs after the fix: BEFORE FIX (environment VARIABLE leaks to child processes): # Global leak scenario (as in the pre-fix tests) ENV['DATABASE_URL'] = 'sqlite3:/tmp/leaked_before.sqlite3' puts "PARENT sees DATABASE_URL => #{ENV['DATABASE_URL']}" # A child process started by the test (or rake task) would inherit the environment # The child would also see the DATABASE_URL value system("ruby -e 'puts \"CHILD sees DATABASE_URL=\" + ENV[\'DATABASE_URL\'].to_s'" ) AFTER FIX (scoped env, no leakage): def with_env(key, value) old = ENV[key] ENV[key] = value begin yield ensure ENV[key] = old end end with_env('DATABASE_URL','sqlite3:/tmp/leaked_after.sqlite3') do # Inside this block, DATABASE_URL is set for the duration, but it is not visible to child processes launched outside system("ruby -e 'puts \"CHILD sees DATABASE_URL=\" + (ENV[\'DATABASE_URL\'] || "").to_s'" ) end # Outside the block, DATABASE_URL should be nil or unchanged puts "PARENT after block sees DATABASE_URL => #{ENV['DATABASE_URL'].inspect }"

Commit Details

Author: zzak

Date: 2025-12-29 06:02 UTC

Message:

Don't leak DATABASE_URL to env in railties/dbs_schema_test ``` Failure: ApplicationTests::RakeTests::RakeDbsSchemaTest#test_db:fixtures:load_with_database_url [/home/zzak/code/rails/tools/support/leak_checker.rb:22]: Environment leak detected! DATABASE_URL bin/test test/application/rake/dbs_schema_test.rb:259 Failure: ApplicationTests::RakeTests::RakeDbsSchemaTest#test_db:migrate_and_db:migrate:status_with_database_url [/home/zzak/code/rails/tools/support/leak_checker.rb:22]: Environment leak detected! DATABASE_URL bin/test test/application/rake/dbs_schema_test.rb:44 Failure: ApplicationTests::RakeTests::RakeDbsSchemaTest#test_db:schema:dump_with_database_url [/home/zzak/code/rails/tools/support/leak_checker.rb:22]: Environment leak detected! DATABASE_URL bin/test test/application/rake/dbs_schema_test.rb:134 ```

Triage Assessment

Vulnerability Type: Information Disclosure

Confidence: HIGH

Reasoning:

Commit prevents leaking the DATABASE_URL environment variable during test execution by avoiding setting DATABASE_URL in the global ENV and instead scopes its value within a controlled block. This mitigates potential information disclosure of sensitive database configuration during test runs.

Verification Assessment

Vulnerability Type: Information Disclosure via environment variable (DATABASE_URL) leakage in test environment

Confidence: HIGH

Affected Versions: 8.1.x prior to this commit (pre-07f53df0a9b881ffc040fa57289b5e0316cc3d5d)

Code Diff

diff --git a/railties/test/application/rake/dbs_schema_test.rb b/railties/test/application/rake/dbs_schema_test.rb index 6acd180a1d577..eb218b7e4c766 100644 --- a/railties/test/application/rake/dbs_schema_test.rb +++ b/railties/test/application/rake/dbs_schema_test.rb @@ -20,8 +20,7 @@ def database_url_db_name "db/database_url_db.sqlite3" end - def set_database_url - ENV["DATABASE_URL"] = "sqlite3:#{database_url_db_name}" + def delete_database_config! # ensure it's using the DATABASE_URL FileUtils.rm_rf("#{app_path}/config/database.yml") end @@ -42,8 +41,10 @@ def db_migrate_and_status(expected_database) test "db:migrate and db:migrate:status with database_url" do require "#{app_path}/config/environment" - set_database_url - db_migrate_and_status database_url_db_name + delete_database_config! + with_env DATABASE_URL: "sqlite3:#{database_url_db_name}" do + db_migrate_and_status database_url_db_name + end end test "db:migrate on new db loads schema" do @@ -131,8 +132,10 @@ def db_schema_sql_dump end test "db:schema:dump with database_url" do - set_database_url - db_schema_dump + delete_database_config! + with_env DATABASE_URL: "sqlite3:#{database_url_db_name}" do + db_schema_dump + end end test "db:schema:dump with env as ruby" do @@ -257,8 +260,10 @@ def db_fixtures_load(expected_database) test "db:fixtures:load with database_url" do require "#{app_path}/config/environment" - set_database_url - db_fixtures_load database_url_db_name + delete_database_config! + with_env DATABASE_URL: "sqlite3:#{database_url_db_name}" do + db_fixtures_load database_url_db_name + end end test "db:fixtures:load with namespaced fixture" do
← Back to Alerts View on GitHub →