Our Workflow for Security Releases using GitHub Security Advisories

by | Jul 21, 2021

We recently started using GitHub Security Advisories as part of our workflow for pushing out security releases. This post will give a brief introduction on how they work, how we use them, some of their limitations, and how we overcome them. We are still experimenting with this workflow, but the information could still be helpful for some while others might have suggestions how we could do things better.

GitHub Security Advisories

GitHub Security Advisories are a tool for preparing and publishing security fixes for your software project. When someone discovers a security flaw, you can create a GitHub Security Advisory and invite them to it. In there, you can write your security advisory describing the problem and fixes or workarounds. Once that’s done, you can conveniently request a CVE ID using GitHub, the advisory will then be reviewed and assigned a CVE ID. In the meantime, there is the option to create a private fork of the repository that can be used to prepare and review patches. On that repository, you can create one or more pull requests (in case you need to fix multiple version branches) with all the normal review functionality available. Once everyone is happy with the advisory and the pull requests and you are ready to release, you can merge and publish the advisory. This will automatically merge all of the pull requests that are part of the advisory into the public repository at once. For more details, you can check the quite extensive documentation.

Multiple Advisories for a Release

In case multiple security issues are discovered in quick succession, it makes sense to batch them into a single security release. However, a single GitHub Security Advisory is supposed to cover only a single issue. This for example shows in the fact that one advisory can only be associated with a single CVE ID. One option would be to merely use the temporary private fork to prepare the pull requests with all the fixes and requesting multiple CVE IDs yourself instead of using the convenient feature for this on GitHub. We decided that this was not an option as we wanted to request the CVE IDs via GitHub as well as have separate advisories for different issues.

However, when creating multiple advisories independently, you can end up in a situation where all the pull requests for separate issues were tested individually, but the result of merging all of them was never tested. In the worst case, you could even end up merging one advisory and only then noticing that this actually introduced a merge conflict preventing another one from being merged. Our solution for this was to first prepare them separately and review them until everyone was happy with that state. Next, we put all advisories in an arbitrary order and then rebase each pull request on top of the one from the previous advisory. This ensure that they can be merged in that order without any conflicts. They could even be fast-forwarded, but as we handled them as pull requests, we still ended up with one merge commit for each.

GitHub Actions

For Icinga, we heavily use GitHub Actions to automatically build and test on all platforms and distributions we currently support. One major drawback of the private forks used by GitHub Security Advisories is that they don’t run GitHub Actions. That is another reason for ordering the advisories and then basing each on the previous one: in the private fork of the last advisory, you will have a state that includes all the security fixes and can be used for testing the release before it is published. In case of the recent Icinga 2.12.5 and 2.11.10 releases, we used the last commit on the respective pull request to locally run tests and later prepare the release builds.

This also explains, why this commit was tagged as v2.12.5 instead of the merge commit of the security advisory. We have exported the source code from that commit as a tar.gz and created initially private forks of the repositories on our GitLab instance that we use to build our release packages. In these forks, we then built packages from the tar.gz. This ensured that our tests passed on all Linux distributions we support and that we have the release packages ready right when we publish the advisories and release blog post.

You May Also Like…

Subscribe to our Newsletter

A monthly digest of the latest Icinga news, releases, articles and community topics.