Hard-Coded Secrets
About Hard-Coded Secrets
Configuring Elixir Applications
Elixir applications use several configuration files for different environments and stages of the application life cycle:
config.exs
: Contains configuration that is used across all environments and is loaded at compile time.{env}.exs
: Contains environment-specific configuration (e.g.,dev.exs
,test.exs
,prod.exs
). This is also loaded at compile time.runtime.exs
: Introduced in Elixir 1.11, this file contains configuration that should be loaded and evaluated at runtime.
Secrets Management
Hardcoding secrets in the configuration files (config.exs
, {env}.exs
, or runtime.exs
) can lead to security vulnerabilities, as these secrets might end up in version control systems and could be exposed. It's recommended to use environment variables or a secrets management tool to handle your application secrets.
For instance, instead of hardcoding a secret_key_base
in config.exs
, you could fetch it from an environment variable:
config :my_app, MyApp.Endpoint,
secret_key_base: System.get_env("SECRET_KEY_BASE")
In runtime.exs
, it would look like:
config :my_app, MyApp.Endpoint,
secret_key_base: System.fetch_env!("SECRET_KEY_BASE")
Note the difference: System.get_env/1
used in config.exs
and {env}.exs
files will return nil
if the environment variable isn't set, while System.fetch_env!/1
used in runtime.exs
will raise an error if the environment variable isn't set.
In a production environment, the prod.exs
and runtime.exs
configuration files should not contain hardcoded secrets. Secrets should be read from the environment or a secrets manager.
If a secret_key_base
is hardcoded in config.exs
, it's available in all environments unless explicitly overridden in the environment-specific configuration file ({env}.exs
).
By following these practices, you can ensure a secure and maintainable configuration setup for your Elixir applications.
Rotating Secrets
If hard-coded secrets are detected for a production environment in your Elixir or Phoenix application, these secrets must be rotated. Rotation of secrets refers to the process of invalidating the current secret and replacing it with a new one.
To rotate secrets in Elixir or Phoenix applications:
- Generate a new secret. This can usually be done by running a mix task. For example, in Phoenix you would generate a new secret key base by running
mix phx.gen.secret
. - Replace the old secret in your environment variables or secrets manager with the new secret.
- Update your application configuration to reference the new secret. If you're using environment variables, this might just involve deploying your application with the new environment variables.
- Verify that the application functions correctly with the new secret. Be aware that this could potentially invalidate sessions or tokens that were encrypted or signed with the old secret.
- After confirming the application is functioning correctly for the new secret you don't have to remove the old one from version control as it's no longer valid.
Remember, the critical aspect of secret rotation is that it must happen with minimal disruption to the application services and users. Also, in certain cases, both old and new secrets might need to coexist for a certain period (also called secret rotation window) to avoid service disruption. The length of this period will depend on your application and how it uses these secrets.