Security Best Practices For GitHub Actions Secrets

Davide 'CoderDave' Benvegnù - Sep 26 '23 - - Dev Community

Today we talk about security in GitHub, and specifically about how to properly use and configure GitHub Actions Secrets.

This article is part of a new GitHub Security Hardening series, so stay tuned for new articles about this topic.

Also, if you are new to GitHub Actions, I recommend you to check the intro video I made about the topic, there I cover all you can do with GitHub Actions.

Video

As usual, if you are a visual learner, or simply prefer to watch and listen instead of reading, here you have the video with the whole explanation.

Link to the video: https://youtu.be/2yHRq7aWDKM

If you rather prefer reading, well... let's just continue :)

Let's Talk About Secrets

We hopefully all agree that sensitive values should never be stored as plain text in workflow files, but rather as secrets.

Secrets can be configured at the enterprise, organization, repository, or environment level, allowing you to store sensitive information in GitHub, as I explained in this video.

Storing these secrets is not a problem as everything is safely managed by GitHub. They are even encrypted on the client side before reaching GitHub! However, using them can be problematic.

To help prevent accidental leakages, in fact, GitHub redacts any secrets that appear in run logs and replace their values with stars (***).

GitHub replaces secrets with stars in logs

This redaction looks for exact matches of any configured secrets, as well as common encodings of the values, like for example Base64. There are however multiple ways in which a secret value can be transformed, and because of that this redaction is not 100% guaranteed.

As a result, there are some things we can proactively do, and good practices we should follow, to help ensure secrets are redacted and to limit other risks associated with secrets.

Don't Use Structured Data

First of all, if possible don’t use structured data as a secret. Using structured data can cause secret redaction within logs to fail, as redaction relies on identifying an exact match of the secret value.

Structured vs Unstructured secrets

For example, avoid using a blob of JSON, XML, YAML, or similar as secret value, this significantly reduces the probability that the secrets will be properly redacted.
Instead, create individual secrets for each sensitive value.

Again, this is not always possible, but doing so greatly reduce risks.

Register ALL Secrets

Another important step is to register all secrets used within workflows. If a secret is used to generate another sensitive value within a workflow, that generated value should be formally registered as a secret. This ensures that the value will be redacted if it ever appears in the logs.

Use Secrets in GitHub Actions

For example, when using a private key to generate a signed JWT for accessing a web API, it's important to register that JWT as a secret. Otherwise, the JWT won't be redacted if it ever enters the log output.

It's important to note that registering secrets also applies to any sort of transformation or encoding. If your secret is transformed in any way (for example with Base64 or URL encoding), be sure to register the new value as a secret as well.

Let me know in the comments down below if you like me to produce an article and/or a video on how to register anything as a secret in GitHub Actions.

Audit How Secrets Are Handled

In addition, it is important to audit how secrets are handled. This involves reviewing how secrets are used to ensure they are being handled properly.

To do this, you can review the source code of the repository executing the workflow and check any actions used in the workflow. For example, make sure that secrets are not sent to unintended hosts or explicitly printed to log output.

Source Code of a GitHub Action handling secrets

After testing valid and invalid inputs, view the run logs for your workflow and confirm that secrets are properly redacted or not shown. It is not always clear how a command or tool you are invoking will send errors to STDOUT and STDERR, and secrets may end up in error logs. Therefore, it is good practice to manually review the workflow logs to ensure that secrets are properly handled.

Use Minimally Scoped Credentials

Next, it’s a good practice, and not only for GitHub Actions Secrets, using credentials that are minimally scoped.

Ensure that the credentials used in workflows have the minimum privileges required. Keep in mind that any user with write access to your repository also has read access to all the secrets configured in it.

Setting the proper permissions for the GITHUB_TOKEN

Actions can access the GITHUB_TOKEN from the github.token context and you should ensure that this token is only granted the minimum required permissions. It is good security practice to set the default permission for GITHUB_TOKEN to read access only for repository contents.
The permissions can then be increased for individual jobs within the workflow file, as required.

Audit and Rotate Registered Secrets

Another thing we should all do when working with secrets is to audit and rotate registered secrets.

For example, we can periodically review the registered secrets to confirm they are still required and remove those that are no longer needed. I personally set this as a recurrent task for my team so every months we have a review of all secrets.

Security audit task in Jira

We should also rotate secrets periodically to reduce the window of time during which a compromised secret is valid.

Require Approval for Accessing Secrets

And final good practice, consider requiring review for access to secrets.

Not everyone may be aware of this, but you can use required reviewers to protect environment secrets. A workflow job cannot access environment secrets until a reviewer grants approval.

Secrets access with approval in GitHub Actions

This is of course only available in GitHub Enterprise or on public repositories, but it is something you should definitely do if you can.

Conclusions

Let me know in the comments below if you have any other tip and best practices when working with GitHub Secrets.

Also, check out this video, in which I explain how to properly store Secrets in GitHub.

Like, share and follow me 🚀 for more content:

🆘 Get Help With DevOps
📽 YouTube
Buy me a coffee
📧 Newsletter
🌐 CoderDave.io Website
👕 Merch
👦🏻 Facebook page
🐱‍💻 GitHub
👲🏻 Twitter
👴🏻 LinkedIn
🔉 Podcast
💖 Patreon

Buy Me A Coffee

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .