How to Safely Store Secrets in GitHub
Last Updated on September 16, 2024
Everyone has a secret. Small or big, it doesn’t matter. The important thing is that each of us hides such a secret from the world for a variety of reasons. But there’s one thing all secrets have in common – no one wants them to become public!
In the IT world, this is doubly important and I will explain why in a moment. But first, let’s clarify what “secret” means. Let me quote a short definition from the IBM website:
“A secret is a piece of sensitive information. For example, an API key, password, or any type of credential that you might use to access a confidential system.”
As you can see above, the loss of secrets in information systems has far-reaching consequences, because data loss can cause huge financial losses, a breakdown in trust, or even the complete end of our business. So be careful! Keeping secrets is crucial.
Where are secrets stored in GitHub?
Before we think about how and where we can hide such information, let’s first answer the question – why put it in the repository at all?
And the answer is very simple – GitHub Actions. Exactly, I mean the passwords necessary to run individual workflows. As an introduction to the topic and its security, I recommend reading one of our previous texts about GitHub Actions.
Well, somehow GitHub needs this data to execute a specific job in our workflow. That is why a special storage mechanism for such secrets was created. We can create them on several levels: repository, environment, or organization.
When a workflow run is added to the queue, then organization and repository-level secrets are read. In turn, the environment-level secrets are accessed when the job starts.
We can, and even should, limit access to this secret information to the maximum by properly configuring access secrets. Make sure to properly grant access and permissions! For example, for environment-level secrets, we can assign a given reviewer who will manage access. Thanks to this, each workflow job will have to receive such access to be able to access a given secret. A very useful function and extremely important from the security perspective and management of our project.
How to add the secrets in GitHub?
Let me show you now how easy it is to add a secret. It looks similar for all three levels, i.e. in the Settings tab, we have to select the appropriate option and then create a secret that interests us. Before we get started, it’s also worth reading about the naming convention and GitHub secrets pattern. For our needs, I will quote three important points regarding the nomenclature:
- Secret names must not start with the GITHUB_ prefix.
- Secret names must not start with a number.
- Secret names are not case-sensitive.
More information can be found in the official documentation.
To create repository secrets or environment-level secrets you must be either the repository owner or you must have admin access to it. Environment secrets play a crucial role in enhancing security by allowing the creation and management of secrets at an environment level, ensuring that only authorized reviewers can approve workflow runs that access these secrets.
For the organization level, you also need to have admin access but in addition, you can use a policy for a personal account repository. So here is the answer to the question “Who can see GitHub secrets?”. It depends on the access to the repository/organization. Please be aware that anyone who can create or edit the workflow file can also use and read encrypted secrets in that workflow.
💡 PRO tip: Converting plain text files into an encrypted file using tools like SOPS or gpg is crucial for maintaining security while allowing certain parts to remain in plaintext for ease of access.
Every secret you need to create on the Settings menu in GitHub. Either on the repository or organization level.
Environment level
First, we have to choose the environment we are interested in, and then in the lower section of this submenu, we will find a place where the secrets that have already been created are kept. Of course, we can add a new one at any time.
It is worth returning to the topic of access protection and the security of our secrets. It is for this level that we can add additional protection rules like manual approvals and timeouts or even branch limitation rules:
Organization level
First, we have to choose the environment we are interested in, and then in the lower section of this submenu, we will find a place where the secrets that have already been created are kept. Of course, we can add a new one at any time.
It is worth returning to the topic of access protection and the security of our secrets. It is for this level that we can add additional protection rules like manual approvals and timeouts or even branch limitation rules:
Repository level
Here, the matter is quite obvious, we enter the repository we are interested in, select the Settings menu at the top, then the Secrets submenu, here we choose whether we are focused on Actions or Dependabot level, and then click the “New repository secret” button.
From this level, if our repo also has environment or organization secrets, they will be shown here too:
You can also manage a secret file by encrypting sensitive files using gpg before committing them to the repository, ensuring that secrets are not revealed in workflow logs.
GitHub Actions secret example
When creating our actions, we can easily refer to the secrets prepared in such a way through a simple context “secrets”. Thanks to this, we can be sure that even when someone gains access to the definition of our action or the entire repo (but without admin access), our data will still remain safe and our secret values will be hidden.
There is also the issue of safety and best practices. GitHub in its documentation warns that it will automatically redact secrets printed to the log, and at the same time encourages us not to print this information to the log intentionally.
Another way to increase our security is to mask values in logs. To do this, we must precede the given log with the sequence ::add-mask::, and as a result, instead of printing the critical data, the ‘*’ symbols will appear in the log. Examples of the use of such masks:
echo “::add-mask::${{ secrets.MY_SECRET }}”
It is also worth paying attention to any third-party GitHub actions in our project. To be clear, I do not advise against using them. On the contrary. We just have to be careful because we are ultimately responsible for what we do with our project. It’s a good idea to fork a given action and then use it in our project. Then we have a guarantee that no one from the outside will change its operation.
Conclusion
All in all, using GitHub action secrets is a good solution, and with the right level of control and consideration, it is a secure solution to keep your passwords private. Remember to carefully grant permissions in our repositories and control them on an ongoing basis. In case of any threat or attack, any user with write access can create a dedicated workflow to expose our secrets.
[FREE TRIAL] Ensure compliant DevOps backup and recovery with a 14-day trial 🚀
[CUSTOM DEMO] Let’s talk about how backup & DR software for DevOps can help you mitigate the risks