Github is the most ubiquitous software development tool out there with hundreds of articles dedicated to properly securing and defending stored code. It’s quite surprising that the threat model remains poorly defined or understood at most enterprises. Github has become one of (or possibly) the most valuable and important assets at any company managing software development. It stores code, libraries, dependencies and an array of other intellectual property. GitHub Actions can automate build, test and deployment pipelines for software projects (CI/CD). These workflows can be incredibly useful but potentially dangerous ways to automatically build code, run tests, analyze code, deploy to multiple environments, push containers, etc. The potential damage at these companies from an adverse action to or within Github could be disastrous. The attack methods are fairly standard. There are numerous avenues to exploit. Any action could in theory affect the entire user population. And there are reasonable methods to reduce the chances of discovery. There are several ways to access GitHub: The most prevalent and well known way to gain access is to use the website with a user name and a password. Some organizations have Single Sign On (SSO) enabled, while others do not.Another commonly understood way into GitHub is via API access via a personal access token. Two types exist (classic and new). Certain components of the API only work with one or the other type of token. Some have granular controls.Codespaces function in the browser to make tasks easier since they don’t have to be done locally.Git access via SSH or HTTPS using username/pass, ssh key, or personal access token to authenticate. The most prevalent and well known way to gain access is to use the website with a user name and a password. Some organizations have Single Sign On (SSO) enabled, while others do not. Another commonly understood way into GitHub is via API access via a personal access token. Two types exist (classic and new). Certain components of the API only work with one or the other type of token. Some have granular controls. Codespaces function in the browser to make tasks easier since they don’t have to be done locally. Git access via SSH or HTTPS using username/pass, ssh key, or personal access token to authenticate. And there are a wide array of attacks: Untrusted code in privileged workflowsCode injectionsVulnerable actionsImposter commitsCaching issues Untrusted code in privileged workflows Code injections Vulnerable actions Imposter commits Caching issues Privileged workflows are workflows that can write permissions to any GitHub resources, access secrets and/or produce sensitive artifacts. Privileged workflows can be prompted to run untrusted code when checking out to an external pull request. Be sure that permissions are restricted to read only and don’t allow CI pipelines to run from untrusted authors. Malicious code can be injected into workflows through untrusted inputs, untrusted files or through environment files. Data might be attacker controlled and should therefore be treated as potentially untrusted input. If workflows share information through artifacts and the first workflow is compromised, the artifact may also be compromised which could then inject code into the second workflow. When environment files are assigned untrusted content and then used to define environment variables, those variables can have code injected. Restrict token permissions to the absolute minimum required. Validate inputs within environment files. GitHub actions could also be malicious (for further information, see here) and thereby change files, compromise articles, abuse workflow permissions or otherwise inject code. Use GitHub-owned actions where possible. Check for open vulns in other actions. As we previously mentioned, restrict token permissions to the absolute minimum required. And use dependabot to keep actions up to date. here Imposter commits pretend to be in the original repo but actually belong to a fork. Stick to released versions and ensure that the new hashes belong to the original repository by confirming that there is no warning on the commit web page. Caching can break job isolation, disclose sensitive information in the repo, and cached can be used to move laterally (which could then compromise privileged workflows). If one job is running untrusted code, all the jobs should be considered untrusted. Do not cache sensitive information and do not run untrusted code in the default branch. Unfortunately, there are far too many ways to get in with far too few controls in place for prevention. Furthermore, there is no simple answer, option, tool or process that can fix the issue. But while there is currently no simple answer, there are several things you can do to make it better: Depending on the org, may not be able to enforce them all. Some are stronger/weaker. Some companies require SSO but once you implement Okta, that's not really viable. Depending on the org, may not be able to enforce them all. Some are stronger/weaker. Some companies require SSO but once you implement Okta, that's not really viable. To improve security, SSH keys need to be approved and used with SSO auth. GitHub recommends a specific process. Start by ensuring you have a linked SAML identity or create a linked identity by authenticating to your organization with IdP). This will authorize the token until it is revoked manually by the owner, it regenerates or it expires. (If it is revoked, you’ll need to create and authorize a new one.) To improve security, SSH keys need to be approved and used with SSO auth. GitHub recommends a specific process. Start by ensuring you have a linked SAML identity or create a linked identity by authenticating to your organization with IdP). This will authorize the token until it is revoked manually by the owner, it regenerates or it expires. (If it is revoked, you’ll need to create and authorize a new one.) And while numerous articles have been written on GitHub secrets management, it remains a security challenge as secrets continue to leak. GitHub personal access tokens have very distinct formats with clear prefixes to otherwise supposedly random values. These tokens replace GitHub passwords for authenticating in the command line or with an API. This makes it trivial to write a regex that can reliably identify GitHub tokens (separate from other API keys). And while numerous articles have been written on GitHub secrets management, it remains a security challenge as secrets continue to leak. GitHub personal access tokens have very distinct formats with clear prefixes to otherwise supposedly random values. These tokens replace GitHub passwords for authenticating in the command line or with an API. This makes it trivial to write a regex that can reliably identify GitHub tokens (separate from other API keys). The big difference between the classic and new personal access tokens are the scoping and lifetimes, and certain APIs are only accessible with one of them. API keys that never expire are bad practice but rotating them or adjusting their scope is often a non-trivial effort. The big difference between the classic and new personal access tokens are the scoping and lifetimes, and certain APIs are only accessible with one of them. API keys that never expire are bad practice but rotating them or adjusting their scope is often a non-trivial effort. SSH certificates are another alternative to SSH key pairs and they offer a range of improvements. Rather than an end user generating a key pair and uploading their private key, a trust relationship is created between GitHub and a Certificate Authority (CA). The user can request certificates (which can be short lived) that are backed by a private key they control. In the ideal case, the private keys will be stored in hardware, such as a Yubikey, making them difficult to steal. The CA can verify attributes of the private key before issuing a certificate, ensuring that they are strong and that there are consistent controls around them unlike standard SSH key pairs. SSH certificates are another alternative to SSH key pairs and they offer a range of improvements. Rather than an end user generating a key pair and uploading their private key, a trust relationship is created between GitHub and a Certificate Authority (CA). The user can request certificates (which can be short lived) that are backed by a private key they control. In the ideal case, the private keys will be stored in hardware, such as a Yubikey, making them difficult to steal. The CA can verify attributes of the private key before issuing a certificate, ensuring that they are strong and that there are consistent controls around them unlike standard SSH key pairs. We often have long conversations with security teams about defining their crown jewels. There are journals and news articles many times a year extolling this need. GitHub is almost always on the short list for software and technology companies (and for many others). Hence thoroughly protecting GitHub should arguably be on most cybersecurity organizations’ priority list.