Api Key Exposure in Rails with Cockroachdb
Api Key Exposure in Rails with Cockroachdb — how this specific combination creates or exposes the vulnerability
Api key exposure in a Ruby on Rails application that uses CockroachDB can occur through multiple vectors, and the combination of Rails conventions and CockroachDB-specific integrations introduces distinct risks. When Rails applications interact with CockroachDB, developers often rely on ActiveRecord configurations that may inadvertently expose sensitive credentials or API keys through logs, error messages, or misconfigured environment handling.
One common scenario involves the database.yml configuration where CockroachDB connection strings include API keys or authentication tokens. If these files are committed to version control or improperly managed, keys can be leaked. CockroachDB connection strings typically contain sensitive parameters such as sslcert, sslkey, and sslrootcert, and if API keys are embedded directly in these strings, they become accessible to anyone with access to the repository or server filesystem.
Additionally, Rails logging can expose API keys when queries are logged in development or improperly configured production environments. CockroachDB's wire protocol interactions with ActiveRecord may include authentication tokens in logs if sensitive parameters are not filtered. For example, a standard database query log might inadvertently include credentials if the logging level is set too verbosely or if custom log formatting includes full connection parameters.
Environment variables are another exposure point. Rails applications often load database credentials from ENV variables, and if API keys are stored in the same environment as other configuration values, they risk being exposed through process listings, error reports, or debugging endpoints. CockroachDB-specific environment setups may inadvertently expose these keys through misconfigured startup scripts or container orchestration configurations.
The interaction between Rails' ActiveRecord and CockroachDB's PostgreSQL compatibility layer can also create indirect exposure. When developers use raw SQL queries or dynamic finder methods, they might concatenate API keys or authentication tokens directly into query strings. This practice can lead to keys appearing in logs, error traces, or application monitoring tools, especially when error handling is not properly sanitized.
Cockroachdb-Specific Remediation in Rails — concrete code fixes
Remediation focuses on secure credential handling, logging hygiene, and strict separation of sensitive data from application code. The following examples demonstrate secure practices for integrating CockroachDB with Rails while minimizing API key exposure.
1. Secure database.yml configuration with encrypted credentials
Instead of embedding API keys directly in config/database.yml, use Rails encrypted credentials or environment variables. Example of a secure configuration:
# config/database.yml
production:
url: <%= ENV["COCKROACHDB_DATABASE_URL"] %>
sslcert: <%= ENV["COCKROACHDB_SSL_CERT"] %>
sslkey: <%= ENV["COCKROACHDB_SSL_KEY"] %>
sslrootcert: <%= ENV["COCKROACHDB_SSL_ROOT_CERT"] %>
variables:
application_name: myapp-prod
retryable_transactions: 'true'
2. Using encrypted credentials for sensitive parameters
Store API keys and sensitive parameters in Rails encrypted credentials (config/master.key and config/credentials.yml.enc). Never store keys directly in version control.
# config/credentials.yml.enc (decrypted view for illustration only)
cockroachdb:
api_key: <%= ENV.fetch("COCKROACHDB_API_KEY") { "encrypted_default_key" } %>
ssl_password: <%= ENV.fetch("COCKROACHDB_SSL_PASSWORD") { "encrypted_ssl_password" } %>
# Usage in initializers or models
cockroach_config = Rails.application.credentials.dig(:cockroachdb)
APIClient.configure do |config|
config.api_key = cockroach_config[:api_key]
config.ssl_password = cockroach_config[:ssl_password]
end
3. Secure connection string construction with placeholders
Construct connection strings programmatically without exposing keys in logs or configuration files:
# app/services/cockroachdb_connector.rb
class CockroachdbConnector
def self.connection
@connection ||= begin
require 'pg'
conn_params = {
host: ENV.fetch("COCKROACHDB_HOST", "localhost"),
port: ENV.fetch("COCKROACHDB_PORT", 26257),
dbname: ENV.fetch("COCKROACHDB_DATABASE", "app_production"),
user: ENV.fetch("COCKROACHDB_USER", "app_user"),
password: ENV.fetch("COCKROACHDB_PASSWORD"),
sslmode: ENV.fetch("COCKROACHDB_SSL_MODE", "require"),
sslcert: ENV.fetch("COCKROACHDB_SSL_CERT"),
sslkey: ENV.fetch("COCKROACHDB_SSL_KEY"),
sslrootcert: ENV.fetch("COCKROACHDB_SSL_ROOT_CERT")
}
PG.connect(conn_params)
end
end
end
4. Sanitizing logs and error reporting
Configure Rails and CockroachDB logging to filter sensitive parameters. Use Rails parameter filtering and custom log formatting to prevent API key leakage in logs:
# config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [:api_key, :ssl_password, :auth_token]
# config/initializers/cockroachdb_logging.rb
if Rails.env.production?
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.logger.formatter = proc do |severity, datetime, progname, msg|
# Filter sensitive patterns from logs
filtered_msg = msg.to_s.gsub(/api_key=[^&]*/, 'api_key=[FILTERED]')
filtered_msg = filtered_msg.gsub(/password=[^&]*/, 'password=[FILTERED]')
"#{datetime}: #{severity} -- : #{filtered_msg}\n"
end
end
5. Environment isolation and secret management
Use separate environment variables for different deployment environments and integrate with secret management tools. Never hardcode API keys in initializers or models.
# config/initializers/cockroachdb_client.rb
api_key = ENV.fetch("COCKROACHDB_API_KEY")
raise "COCKROACHDB_API_KEY is required" if api_key.blank?
CockroachdbApiClient.configure do |config|
config.api_key = api_key
config.endpoint = ENV.fetch("COCKROACHDB_ENDPOINT", "https://api.cockroachdb.example.com")
config.timeout = 30
end