Governance of 3rd party GitHub Actions in GHES instances

After spending a few years using GitHub Actions in Open Source, Commercial, and FedRamp environments, I wanted to share some of my takeaways for a few options on how to provide governance over what Actions you allow to be used within your self-hosted GHES and Actions runner instances. This article will focus on government or commercial users self-hosting source code (GHES) and the Actions runners in their secured environments.

There are two paths if you boil this down:

  • Enabling GitHub Connect within GHES (nearly effortless)
  • A hybrid approach of using actions-sync and a dedicated GH Organization to host your authorized 3rd party Actions (balance of security and convenience)

GitHub Connect is the easiest by far. You can link your GHES instance to your public GitHub.com Enterprise Account and, with a click, begin allowing your teams to start writing Workflows referencing Actions hosted on GitHub.com. With Connect, when one of your Actions workflows referencing a 3rd party Action (eg, docker/build-push-action@v3) runs, the Runner environment will be allowed to grab the Action at the major version tag specified from the public repo on github.com. This is convenient but also opens you up to some relatively major security concerns around a bad actor poisoning an upstream supply chain. The docker Org example is typical, but once you open the Actions floodgates to your Engineers, you’ll find them wanting to use all kinds of Actions you’ve never heard of - and how good do you feel about that from a security and governance perspective? You can set Actions policies at an Enterprise level to mitigate concerns, allowing them individually. I’ve found this a bit kludgy at times and hard to manage, as GHES requires you to specify specific tags or SHAs for each, and that can get fragile and has a bit of a “toil” smell to it if you want to keep Action’s code fresh.

If you’ve gone through all the trouble and cost to self-host GitHub in your Enterprise environment, there should be an extensive list of reasons why you did that. Cybersecurity and regulatory requirements are likely the main drivers behind the decision. Given what I’ve outlined above, it seems strange that one would enable GitHub Connect in a self-hosted GHES environment…

A hybrid approach makes the most sense. It gives InfoSec teams more peace of mind. You’re not allowing bleeding-edge 3rd party Actions repositories to be pulled directly into your high-security GHES environments at runtime. The convenience factor is significant, but if you go to the trouble to self-host all this for security reasons, you should not enable GitHub Connect.

The simplest and most effective way to do this, in my experience, is to create a “jail” for these 3rd party Actions sourced from GitHub.com. Doing so allows you to layer on additional governance around who can write to these and read from them at the Organizational level within GHES permissions.

A simple way to get started is to create a “bot” account in GHES that can write to an Org named “external-actions” or similar that’s easy to remember and immediately signals its intent.

Create a repo outside that Org where your users can submit Pull Requests. This repo will host the following:

  • A list of 3rd party Actions to sync from GitHub.com
  • A list of GitHub-owned Actions to sync from GitHub.com

Using a GitOps approach, you can manage this “external-actions” Org and all the Actions repos hosted within it entirely through this repo and a couple of Actions workflows that live within it. Add a Secret for your bot account so it has write access to this unique external-actions Organization.

Use the actions-sync CLI tool inside a custom Actions Workflow to read from a structured file in your PR-able git repo and then sync these specific Actions from GitHub.com into your “external-actions” Organization in GHES when that Workflow runs upon commit to your default branch (eg, your team approves and merges a user-generated PR where they request a popular 3rd party Action to sync into your GHES environment.)

You can then set an Enterprise Actions policy in GHES to only allow Actions to be sourced and executed from this “external-actions” Organization. You’ve now successfully implemented 3rd party Actions workflow governance. You can also create a similar Workflow to run on a weekly or similar cadence that will sync in the github.com/actions Org’s repos (things like setup-go, setup-python, cache) and github.com/github Org’s repos (CodeQL, Dependabot.) Doing so allows you to avoid turning on GitHub Connect entirely while giving you much greater control over what Actions you allow to run in your CI/CD environment(s).

I hope this helped provide some guidance on additional governance over 3rd party Actions in your high-security GitHub environments. Don’t hesitate to contact me if you’d like to discuss further or think I’ve missed something!

- Kevin