Secure your workflows with StepSecurity Harden Runner
In my previous article, Secure your .NET builds with StepSecurity and GitHub Actions, I discussed software supply chain attacks and showed how to use StepSecurity Secure Workflows to improve the security of your GitHub Actions software supply chain. In this article I show how to use the Harden Runner security agent to audit and block outbound connections to further improve workflow security.
A Quick Recap
Software supply chain attacks are an increasing threat that targets source code, build processes or update mechanisms to infect legitimate apps and distribute malware. Incidents like the SolarWinds attack have breached all types of organisation ranging from startups to Fortune 500 companies and government agencies.
StepSecurity helps secure your software release and distribution supply chain. Secure Workflows provides remediation of vulnerabilities in GitHub Actions workflows and the Harden Runner security agent prevents exfiltration of credentials and helps detect compromised dependencies, tools or source code.
What is Harden Runner?
As seen in recent supply chain attacks, including the Codecov breach and malicious npm cryptomining packages, compromised dependencies and build tools typically make outbound calls. Restricting outbound traffic to only the endpoints needed for the workflow thwarts many software supply chain attack vectors.
When added to a job in a GitHub Actions workflow, the Harden Runner security agent can audit and block outbound traffic from the runner executing that job. There are some limitations:
- Harden Runner only works for GitHub hosted runners, self-hosted runners are not supported.
- Only Ubuntu runners are supported, Windows and macOS runners are being discussed.
- Harden Runner does not support running an entire job in a container, which is unusual for GitHub Actions.
Harden Runner supports both public and private repositories. If you use Harden Runner with a private repository the generated audit report is not public, authentication is required and only those who have access to the repository can view the report.
How do I set up Harden Runner?
The easiest way to add Harden Runner to a workflow is to use the Secure Workflows app. This can set the minimum GITHUB_TOKEN
permissions for the workflow, pin the Actions used by a full length commit SHA and add the Harden Runner Action to the start of each job in audit
mode. Future runs of the workflow will include a link to an audit report that lists all the outbound calls made in the workflow log.
For private repositories you also need to install the Harden Runner app on GitHub which requires actions: read
permissions to your repositories. I've also installed the app for my public repositories because otherwise you have to wait 30 seconds for the results and I'm impatient.😄
How do I configure block mode?
With Harden Runner added to your workflows you continue to develop your project while it audits outbound connections. Once you have completed several runs of a workflow you can check the audit reports and build a list of allowed connections. Simple workflows like project management tasks may always make the same connections but more complicated workflows may include optional calls so it is worth checking several runs rather than relying on the results of just one audit.
The audit report lists every step in a job. If a step makes any outbound connections the domain is listed along with the name of the process that made the connection. If a workflow includes multiple jobs then each job has its own tab in the report.
The audit report also provides the YAML needed to configure Harden Runner to block any outbound connections from the job other than those listed in the report.
Once you configure Harden Runner in block
mode, it will restrict outbound traffic from the workflow to only the domains listed.
What happens when a call is blocked?
Calls to any domain not allowed by Harden Runner will fail DNS resolution and cause the step that made them, and the job, to fail. So let's test that out...
I added the following step to the same CI build workflow used for the audit screenshots above:
- name: Test Harden Runner
run: curl -X GET https://blog.taranissoftware.com/
This uses curl
to access a URL that is not in the list of allowed endpoints provided to Harden Runner. Immediately we can see in the pull request that there is a problem:
Clicking through to the workflow summary we can see that an attempt was made to access a restricted endpoint and was blocked at the DNS level:
The workflow logs show it was our test step that tried to access the restricted domain:
And, we can also see the details of the step, process and blocked endpoint in the Harden Runner report:
Tips for .NET Developers
Since Harden Runner only works on an Ubuntu runner you can't use it for jobs that require a Windows or macOS runner such as building .NET Framework, Xamarin or .NET MAUI apps but it does work for building .NET Core, .NET 5 and .NET 6 apps that will build on Linux.
Disable .NET Telemetry
The .NET CLI includes telemetry that sends data back to Microsoft. When running the CLI in a build environment you should disable the telemetry because otherwise commands like dotnet build
and dotnet restore
will make additional calls. To disable the telemetry add the following environment variables to your workflow:
env:
DOTNET_NOLOGO: true # Disable the .NET logo in the console output
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true # Disable the .NET first time experience
DOTNET_CLI_TELEMETRY_OPTOUT: true # Disable sending .NET CLI telemetry to Microsoft
This should also reduce the workflow duration slightly, which is a nice bonus.
Setup .NET
In my projects the action to set up .NET (actions/setup-dotnet) is inconsistent - sometimes it makes two outbound calls and other times it makes three. This is a good example of why you need to audit multiple runs of a workflow before enabling block
mode because the list of allowed connections needs to include all possible calls. From my experience the set up .NET action needs these connections:
dotnetbuilds.azureedge.net:443
dotnetcli.azureedge.net:443
dotnetcli.blob.core.windows.net:443
Final Thoughts
Harden Runner requires some time to fully configure but once blocking is enabled it thwarts many common attack vectors. Between Secure Workflows and Harden Runner, StepSecurity have added two powerful tools to the DevSecOps toolkit for developers using GitHub Actions. Whether you're working on open or closed source projects I reccommend you check them out and improve the security of your software supply chain.
Cover image contains a vector created by upklyak from www.freepik.com.
Software Supply Chain Attacks chart is from Sonatype's 2021 State of the Software Supply Chain report.
Subscribe to my newsletter
Read articles from Dave Murray directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Dave Murray
Dave Murray
.NET developer with a passion for mobile and DevOps. I build cross platform apps using Xamarin, backend systems using Azure and GitHub Actions using Docker.