Compare commits

..
Author SHA1 Message Date
dependabot[bot] 9462746bdb Bump github/codeql-action from 3.25.13 to 4.31.9
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.13 to 4.31.9.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/2d790406f505036ef40ecba973cc774a50395aac...5d4e8d1aca955e8d8589aabd499c5cae939e33c7)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.9
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-16 23:03:46 +00:00
Varun Sharma 20cf305ff2 Merge pull request #622 from step-security/feature/custom-property-skip
Feature/custom property skip
2025-12-09 11:28:11 -08:00
Varun Sharma c51e8eeb6c feat: skip agent install and post step on subsequent runs for GitHub-hosted runners 2025-12-07 22:01:18 -08:00
Varun Sharma e152b90204 feat: skip harden-runner based on repository custom property 2025-12-07 21:54:18 -08:00
Varun Sharma ee1faec052 feat: replace skip-harden-runner with skip-on-custom-property input 2025-12-07 21:54:10 -08:00
Varun Sharma 1dc7c17646 feat: add skip-harden-runner input to conditionally skip execution 2025-12-07 21:54:01 -08:00
Varun Sharma df199fb7be Merge pull request #620 from step-security/rc-29
Release v2.13.3
2025-12-01 20:45:08 -08:00
Varun Sharma 03d096a772 update agent 2025-11-30 21:07:45 -08:00
Varun Sharma 40901073af fix: update agent 2025-11-30 07:46:48 -08:00
Varun Sharma 95d9a5deda Merge pull request #606 from step-security/rc-28
Release v2.13.2
2025-11-04 23:36:48 -08:00
Varun Sharma 87e429d3fb Update limitations.md 2025-11-04 22:15:02 -08:00
Varun Sharma ef891c3a30 feat: add support for custom vm image 2025-11-04 17:02:50 -08:00
Varun Sharma 1fa8c8a8b1 update agent 2025-11-04 16:44:00 -08:00
Ashish Kurmi 92c522aaa6 Merge pull request #593 from step-security/ak-readme-updates
README updates
2025-09-26 09:42:07 -07:00
Ashish Kurmi 4719ad5578 README updates 2025-09-26 09:39:29 -07:00
Ashish Kurmi 4fde639ab4 Merge pull request #591 from eromosele-stepsecurity/Upd
Update README.md
2025-09-26 09:29:32 -07:00
eromosele-stepsecurity f682f2f2d0 Update README.md 2025-09-15 13:51:28 +01:00
Varun Sharma f4a75cfd61 Merge pull request #588 from step-security/rc-26
Release v2.13.1
2025-09-09 10:51:44 -07:00
Varun Sharma 95503d076c ci: remove code-review workflow 2025-09-09 10:19:03 -07:00
Varun Sharma 4b250a0739 ci: add job to confirm dist is as expected 2025-09-09 10:15:51 -07:00
Varun Sharma 5b0ab6abcf update dependencies 2025-09-06 11:46:22 -07:00
Varun Sharma d11f2c1d65 fix bug where status code was not being preserved 2025-09-06 11:34:53 -07:00
Varun Sharma b3fc98e4df improve error handling for policy store sceanrio 2025-09-06 11:26:42 -07:00
Varun Sharma 92fc5d4bf7 update error message 2025-09-06 08:41:22 -07:00
Varun Sharma b61b0a4938 policy store improvements
Only fail the job if ID token is not available
2025-09-06 08:20:33 -07:00
Varun Sharma e3d3f2baea use GitHub release instead of packages 2025-09-06 07:54:01 -07:00
Varun Sharma 646ac01e72 update agent 2025-09-05 11:31:24 -07:00
Varun Sharma 7bc18df383 update agent 2025-09-04 18:06:48 -07:00
Varun Sharma 17d38b322b update agent 2025-08-18 21:37:25 -07:00
Varun Sharma ec9f2d5744 Merge pull request #565 from step-security/rc-24
Release v2.13.0
2025-07-15 12:29:13 -07:00
Varun Sharma 04bcbc31cf update agent 2025-07-15 08:37:07 -07:00
Varun Sharma 7c7a56fcaa feat: get job summary from API 2025-07-13 22:59:51 -07:00
Varun Sharma 6c439dc8bd Merge pull request #562 from step-security/rc-22
Release v2.12.2
2025-06-29 23:07:55 -07:00
Varun Sharma bf5688696d update agent 2025-06-27 09:10:55 -07:00
Varun Sharma 5436dac7b5 update agent 2025-06-26 00:54:04 -07:00
Varun Sharma 88d305a353 update agent 2025-06-19 23:18:49 -07:00
Varun Sharma b976878278 update agent 2025-06-18 00:47:43 -07:00
Varun Sharma 875cc92db2 Update agent 2025-06-13 10:57:36 -07:00
Varun Sharma 002fdce3c6 Merge pull request #544 from step-security/rc-21
Release v2.12.1
2025-06-11 07:18:17 -07:00
Varun Sharma 2489e3fcb3 Merge branch 'main' into rc-21 2025-06-10 23:12:51 -07:00
Varun Sharma 75dd441a81 Merge pull request #555 from step-security/dependabot/github_actions/step-security/publish-unit-test-result-action-2.20.0
Bump step-security/publish-unit-test-result-action from 2.19.0 to 2.20.0
2025-06-10 22:00:25 -07:00
dependabot[bot] 4381ace9c4 Bump step-security/publish-unit-test-result-action from 2.19.0 to 2.20.0
Bumps [step-security/publish-unit-test-result-action](https://github.com/step-security/publish-unit-test-result-action) from 2.19.0 to 2.20.0.
- [Release notes](https://github.com/step-security/publish-unit-test-result-action/releases)
- [Commits](https://github.com/step-security/publish-unit-test-result-action/compare/b495e9a82021fc8f34737416de688298581b847d...e88bfc6c0dffc68a1067d63526c80c81f248da11)

---
updated-dependencies:
- dependency-name: step-security/publish-unit-test-result-action
  dependency-version: 2.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-10 23:12:24 +00:00
Varun Sharma a9da90b635 Merge pull request #553 from h0x0er/feat/container-workflows
self-hosted: refactored block-policy apply logic
2025-06-05 00:17:06 -07:00
Jatin a60ef21c0c update 2025-06-05 11:49:58 +05:30
Jatin 4ad512f165 Merge branch 'rc-21' into feat/container-workflows 2025-06-05 11:49:37 +05:30
Jatin 6b41a39235 fixed test case 2025-06-05 11:44:37 +05:30
Varun Sharma fa70c45ca9 update agent 2025-06-04 23:09:21 -07:00
Jatin eb47845632 self-hosted: refactored block-policy apply logic 2025-06-05 11:18:09 +05:30
Varun Sharma 1705d777e5 Merge pull request #550 from step-security/dependabot/github_actions/step-security/publish-unit-test-result-action-2.19.0
Bump step-security/publish-unit-test-result-action from 2.18.0 to 2.19.0
2025-05-30 21:31:42 -07:00
dependabot[bot] 62893838e7 Bump step-security/publish-unit-test-result-action from 2.18.0 to 2.19.0
Bumps [step-security/publish-unit-test-result-action](https://github.com/step-security/publish-unit-test-result-action) from 2.18.0 to 2.19.0.
- [Release notes](https://github.com/step-security/publish-unit-test-result-action/releases)
- [Commits](https://github.com/step-security/publish-unit-test-result-action/compare/cc82caac074385ae176d39d2d143ad05e1130b2d...b495e9a82021fc8f34737416de688298581b847d)

---
updated-dependencies:
- dependency-name: step-security/publish-unit-test-result-action
  dependency-version: 2.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-29 23:56:01 +00:00
Varun Sharma 42a3378d67 update agent version 2025-05-28 18:06:34 -07:00
Varun Sharma f0cb479b0f fix download path 2025-05-14 00:05:34 -07:00
Varun Sharma 9abfa72990 update agent 2025-05-14 00:00:00 -07:00
Varun Sharma 4379a81ea6 update agent to v1.6.5 2025-05-10 17:53:37 -07:00
Varun Sharma 5a5cdce402 update agent 2025-05-05 01:03:16 -07:00
Varun Sharma 1106c3d7dd Update agent 2025-05-02 00:08:57 -07:00
Varun Sharma 0634a2670c Merge pull request #541 from step-security/rc-20
Release v2.12.0
2025-04-21 12:01:51 -07:00
Varun Sharma 2e3c511341 Update action.yml 2025-04-20 21:24:43 -07:00
Varun Sharma 40873e6a41 Update README.md 2025-04-20 21:20:58 -07:00
Varun Sharma 484c2799ec Update README.md 2025-04-17 14:32:50 -07:00
Varun Sharma 4c8582f455 Update agent versions 2025-04-13 23:07:55 -07:00
Varun Sharma e8d595cd66 fix disable_sudo_and_containers bug 2025-04-13 18:03:05 -07:00
Varun Sharma 5d277fc873 fix journalctl related bug 2025-04-13 10:09:49 -07:00
Varun Sharma ff2ab228bd Merge pull request #536 from rohan-stepsecurity/feat/flag/disable-sudo-and-containers
fix: run sudo command only when both disable-sudo and disable-sudo-an…
2025-04-13 10:08:45 -07:00
Rohan Prabhu b81d650d0e fix: run sudo command only when both disable-sudo and disable-sudo-and-dockers is true 2025-04-13 22:13:27 +05:30
Varun Sharma 769df4ef5d Update agent 2025-04-13 08:30:14 -07:00
Varun Sharma a7a8a29fbc Update dist 2025-04-13 08:25:25 -07:00
Varun Sharma 75fd6ee0fe Merge pull request #535 from rohan-stepsecurity/feat/flag/disable-sudo-and-containers
feat: add new flag disable-sudo-and-containers
2025-04-13 08:22:02 -07:00
Rohan Prabhu 86338660c4 feat: add new flag disable-sudo-and-containers 2025-04-13 13:24:08 +05:30
Varun Sharma 230ee49196 Update agent 2025-04-12 07:40:55 -07:00
Varun Sharma 617de1d11d Merge pull request #533 from oskogstad/patch-1
Update version in Getting Started example
2025-04-03 16:28:31 -07:00
Ole Jørgen Skogstad d930a8a3b2 Update version in Getting Started example
Update to SHA `c6295a65d1254861815972266d5933fd6e532bdf` for `v2.11.1`
2025-04-03 14:53:56 +02:00
Varun Sharma c6295a65d1 Merge pull request #530 from step-security/rc-19
Release v2.11.1
2025-04-01 12:08:07 -07:00
Varun Sharma 3e118b145b Improve error handling 2025-04-01 12:01:02 -07:00
Varun Sharma b38e918ba8 Merge pull request #529 from h0x0er/jatin/cache-fix
cache: add support for cache v2
2025-04-01 11:27:27 -07:00
Jatin 0664d30cda cache: added support for cache v2 2025-04-01 23:50:47 +05:30
Varun Sharma b131ca5ebf Merge pull request #524 from step-security/fix/security/GHSA-968p-4wvh-cqc8
Address vulnerabilities
2025-03-20 18:05:33 -07:00
Varun Sharma 2dc9579753 Address vulnerabilities 2025-03-20 16:22:09 -07:00
eromosele-stepsecurity f054d811b5 Update README (#522) 2025-03-18 16:40:04 -07:00
eromosele-stepsecurity 8a09271fed Update Readme (#520) 2025-03-12 18:45:22 -07:00
Varun Sharma 6ec6af7d62 Update readme (#518) 2025-03-08 16:47:00 -08:00
Varun Sharma 539365ba33 Merge pull request #516 from vorburger/patch-1
Update actions/upload-artifact in Scorecards from v3.0.0 to v4.6.1
2025-03-03 21:14:42 -08:00
Michael Vorburger e34e1ce869 Update actions/upload-artifact in Scorecards from v3.0.0 to v4.6.1
Prompted by https://github.com/MariaDB4j/MariaDB4j/issues/1107,

due to https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/.
2025-03-04 05:48:31 +01:00
Varun Sharma 4cfb9f26cc Merge pull request #515 from step-security-bot/stepsecurity_remediation_1741020767
[StepSecurity] ci: Harden GitHub Actions
2025-03-03 08:55:28 -08:00
StepSecurity Bot 8b7e2a634c [StepSecurity] ci: Harden GitHub Actions
Signed-off-by: StepSecurity Bot <bot@stepsecurity.io>
2025-03-03 16:52:50 +00:00
Varun Sharma 18fe9c66a7 Merge pull request #514 from step-security/update-readme
Update readme
2025-03-01 12:59:54 -08:00
Varun Sharma bb31c5e3c0 Update README.md 2025-03-01 10:50:53 -08:00
Varun Sharma bf5f99ab75 Update logo 2025-03-01 10:22:11 -08:00
Varun Sharma db60402296 Update README.md 2025-03-01 10:18:07 -08:00
Varun Sharma 41d3351872 Merge pull request #512 from step-security/varunsh-coder-patch-3
Update runs-on.yml
2025-02-26 15:49:54 -08:00
33 changed files with 124194 additions and 51676 deletions
-23
View File
@@ -1,23 +0,0 @@
name: Code Review
on:
pull_request:
permissions:
contents: read
jobs:
code-review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
disable-sudo: true
egress-policy: block
allowed-endpoints: >
api.github.com:443
int.api.stepsecurity.io:443
- name: Code Review
uses: step-security/ai-codewise@int
+3 -3
View File
@@ -50,7 +50,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@2d790406f505036ef40ecba973cc774a50395aac
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -61,7 +61,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@2d790406f505036ef40ecba973cc774a50395aac
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -75,4 +75,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@2d790406f505036ef40ecba973cc774a50395aac
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7
+3
View File
@@ -3,6 +3,9 @@ name: RunsOn Tests
on:
workflow_dispatch:
permissions:
contents: read
jobs:
test-host-outbound:
runs-on:
+2 -2
View File
@@ -54,7 +54,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- name: "Upload artifact"
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # tag=v3.0.0
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # tag=v4.6.1
with:
name: SARIF file
path: results.sarif
@@ -62,6 +62,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@2d790406f505036ef40ecba973cc774a50395aac # tag=v1.0.26
uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # tag=v1.0.26
with:
sarif_file: results.sarif
+30 -1
View File
@@ -39,8 +39,37 @@ jobs:
run: npm test -- --coverage
- uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
- name: Publish Test Results
uses: step-security/publish-unit-test-result-action@cc82caac074385ae176d39d2d143ad05e1130b2d # v2.18.0
uses: step-security/publish-unit-test-result-action@e88bfc6c0dffc68a1067d63526c80c81f248da11 # v2.20.0
if: always()
with:
files: |
reports/*.xml
build-check:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
with:
disable-sudo: true
egress-policy: audit
allowed-endpoints: >
github.com:443
registry.npmjs.org:443
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Install Dependencies
run: npm ci
- name: Run build
run: npm run build
- name: Check for changes in dist
run: |
if [[ `git status --porcelain dist` ]]; then
echo "Changes detected in dist directory after build:"
git status --porcelain dist
git diff dist
exit 1
else
echo "No changes in dist directory - build is clean"
fi
+52 -21
View File
@@ -1,7 +1,7 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: light)" srcset="images/banner.png" width="400">
<img alt="Dark Banner" src="images/banner-dark.png" width="400">
<source media="(prefers-color-scheme: light)" srcset="images/harden-runner-new.png" width="400">
<img alt="Dark Banner" src="images/harden-runner-new.png" width="400">
</picture>
</p>
@@ -15,31 +15,50 @@
# Harden-Runner
Harden-Runner secures CI/CD workflows by controlling network access and monitoring activities on GitHub-hosted and self-hosted runners. It blocks unauthorized network traffic and detects unusual activity to protect against potential threats. The name "Harden-Runner" comes from its purpose: strengthening the security of the runners used in GitHub Actions workflows.
Corporate laptops and production servers typically have robust security monitoring in place to reduce risk and meet compliance requirements. However, CI/CD runners, which handle sensitive information like secrets for cloud environments and create production builds, often lack such security measures. This oversight has led to significant supply chain attacks, including the SolarWinds and Codecov breaches.
Traditional security monitoring and EDR solutions are ineffective for CI/CD runners due to their ephemeral nature. These tools also lack the necessary context to correlate events with specific workflow runs in a CI/CD environment.
StepSecurity Harden-Runner addresses this gap by providing security monitoring tailored for CI/CD runners. This approach brings CI/CD runners under the same level of security scrutiny as other critical systems, addressing a significant gap in the software supply chain.
### Harden-Runner: Security Incidents Detected
- [Harden-Runner Detected the tj-actions/changed-files compromise](https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised) ([CVE-2025-30066](https://github.com/advisories/GHSA-mrrh-fwg8-r2c3))
- [Harden-Runner Detected a CI/CD Supply Chain Attack in Google’s Open-Source Project Flank](https://www.stepsecurity.io/case-studies/flank)
- [Harden-Runner Detected the NX Build System compromise](https://www.stepsecurity.io/blog/supply-chain-security-alert-popular-nx-build-system-package-compromised-with-data-stealing-malware)
- [Harden-Runner Detected a CI/CD Supply Chain Attack in Microsoft’s Open-Source Project Azure Karpenter Provider in Real-Time](https://www.stepsecurity.io/case-studies/azure-karpenter-provider)
- [Harden-Runner Detected Anomalous Traffic to api.ipify.org Across Multiple Customers](https://www.stepsecurity.io/blog/harden-runner-detects-anomalous-traffic-to-api-ipify-org-across-multiple-customers)
- [Harden-Runner Detected an Unexpected Microsoft Defender Installation on GitHub-Hosted Ubuntu Runners](https://www.stepsecurity.io/blog/how-stepsecurity-harden-runner-detected-unexpected-microsoft-defender-installation-on-github-hosted-ubuntu-runners)
- [Harden-Runner Flagged an Anomalous Outbound Call, Leading to a Docker Documentation Update](https://www.stepsecurity.io/blog/harden-runner-flags-anomalous-outbound-call-leading-to-docker-documentation-update)
### See It in Action
Harden-Runner secures over **8 million CI/CD workflow runs every week**, protecting thousands of pipelines, including those from popular open-source projects by **Microsoft, Google, and CISA**. See how top projects are using Harden-Runner and explore the insights:
➡️ [Who's using Harden-Runner?](https://docs.stepsecurity.io/whos-using-harden-runner)
## Quick Links
- [Getting Started Guide](#getting-started)
- [Why Choose Harden-Runner](#why-choose-harden-runner)
- [Features and Capabilities](#features)
- [Case Studies and Trusted Projects](#trusted-by-and-case-studies)
- [Environment Compatibility Matrix](#environment-compatibility-matrix)
- [How It Works](docs/how-it-works.md)
- [Known Limitations](docs/limitations.md)
- [Join the Discussions](#discussions)
- [Official Documentation](https://docs.stepsecurity.io/harden-runner)
---
## Introduction
Learn how Harden-Runner works through the video below, which shows how it detected a supply chain attack on a **Google** open-source project.
Learn how Harden-Runner works through the video below, which shows how it detected the tj-actions/changed-files compromise. [View the interactive demo here](https://app.storylane.io/share/679y2zgzljov).
<a href="https://youtu.be/Yz72qAOrN9s" target="_blank">
<img src="images/case-study-thumbnail1.png" alt="Harden-Runner detected supply chain attack in a Google open-source project" title="This case study video shows how StepSecurity Harden-Runner detected a CI/CD supply chain attack in real-time in Google’s open-source project Flank">
<a href="https://www.youtube.com/watch?v=oTAJ7Hy7nPU" target="_blank">
<img src="images/case-study.png" alt="Harden-Runner detected the tj-actions/changed-files Breach" title="This case study video shows how StepSecurity Harden-Runner detected the tj-actions/changed-files Breach">
</a>
---
## Getting Started
This guide walks you through the steps to set up and use Harden-Runner in your CI/CD workflows.
This guide walks you through the steps to set up and use Harden-Runner in your CI/CD workflows. For more details, refer to the [official documentation](https://docs.stepsecurity.io/harden-runner).
### **Step 1: Add Harden-Runner to Your Workflow**
@@ -49,11 +68,12 @@ To integrate Harden-Runner, follow these steps:
- Add the following code as the first step in each job:
```yaml
steps:
- uses: step-security/harden-runner@446798f8213ac2e75931c1b0769676d927801858 # v2.10.3
- name: Harden Runner
uses: step-security/harden-runner@c6295a65d1254861815972266d5933fd6e532bdf # v2.11.1
with:
egress-policy: audit
**Tip**: Automate this step by pasting your workflow into the [StepSecurity online tool](https://app.stepsecurity.io/secureworkflow)
**Tip**: Automate this step by pasting your workflow into the [StepSecurity online tool](https://app.stepsecurity.io/secure-workflow)
<details>
<summary>Click to view the full Getting Started Guide</summary>
@@ -65,7 +85,7 @@ Run your workflow. Once completed:
<p align="left">
<img src="images/buildlog1.png" alt="Link in workflow log" >
</p>
- Click on the provided link (e.g., [example link](https://appv2.stepsecurity.io/github/step-security/github-actions-goat/actions/runs/7704454287?jobid=20996777560&tab=network-events)) to access the **Process Monitor View**, which displays:
- Click on the provided link (e.g., [example link](https://app.stepsecurity.io/github/step-security/github-actions-goat/actions/runs/7704454287?jobid=20996777560&tab=network-events)) to access the **Process Monitor View**, which displays:
- **Network events**: Outbound network calls correlated with each step.
- **File events**: File writes tracked during the job.
<p align="left">
@@ -91,11 +111,11 @@ Harden-Runner offers a comprehensive suite of features to enhance the security o
### Community (Free)
- **Block Network Egress Traffic with Domain Allowlist:** Control outbound network traffic by specifying allowed domains, preventing unauthorized data exfiltration.
- **Detect Compromised Packages, Dependencies & Build Tools:** Identify and mitigate risks from malicious or vulnerable components in your build process.
- **CI/CD-Aware Event Correlation:** Each outbound network connection, file operation, and process execution is mapped to the exact step, job, and workflow where it occurs.
- **Automated Baseline Creation:** Harden-Runner builds a baseline for each job based on past outbound network connections.
- **Anomaly Detection:** Once the baseline is created, any future outbound calls not in the baseline trigger a detection.
- **Block Network Egress Traffic with Domain Allowlist:** Optionally use the automatically created baseline to control outbound network traffic by specifying allowed domains, preventing unauthorized data exfiltration.
- **Detect Modification of Source Code:** Monitor and alert on unauthorized changes to your source code during the CI/CD pipeline.
- **Disable Sudo Access:** Restrict the use of superuser privileges in your workflows to minimize security risks.
- **Insights Page for CI/CD Runs:** Access detailed reports and analytics for each CI/CD run to monitor security events and compliance.
### Enterprise (Paid)
@@ -103,11 +123,11 @@ Includes all features in the **Community** tier, plus:
- **Support for Private Repositories:** Extend Harden-Runner's security capabilities to your private GitHub repositories.
- **Support for Self-Hosted Runners:** Apply security controls and monitoring to self-hosted GitHub Actions runners.
- **GitHub Checks Integration:** Enable GitHub Checks for Harden-Runner—if the baseline remains unchanged, the check passes; if it changes, the check fails, showing new outbound connections.
- **View Outbound GitHub API calls at the Job Level:** Monitor HTTPS requests to GitHub APIs
- **Determine Minimum GITHUB_TOKEN Permissions:** Monitor outbound HTTPS requests to GitHub APIs to recommend the least-privilege permissions needed for your workflows, enhancing security by reducing unnecessary access.
- **View the Name and Path of Every File Written During the Build Process:** Gain visibility into every file written to the build environment, including the ability to correlate file writes with processes, ensuring complete transparency.
- **View Process Names and Arguments:** Monitor every process executed during the build process, along with its arguments, and navigate the process tree to detect suspicious activities.
- **Github Checks:** Display Harden Runner insights in the GitHub Checks UI, giving quick feedback on unusual network activity in pull requests.
For a detailed comparison and more information, please visit our [Pricing Page](https://www.stepsecurity.io/pricing).
@@ -117,26 +137,37 @@ Explore the full feature set in the [Features Documentation](https://docs.stepse
## Trusted By and Case Studies
Harden-Runner is trusted by over 5000 leading open-source projects and enterprises, including Microsoft, Google, Kubernetes, and more.
Harden-Runner is trusted by over 8000 leading open-source projects and enterprises, including Microsoft, Google, Kubernetes, and more.
### Trusted by
| [![CISA](https://avatars.githubusercontent.com/u/18539691?s=60&v=4)](https://appv2.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/9947319332?jobid=27479776091&tab=network-events) | [![Microsoft](https://avatars.githubusercontent.com/u/6154722?s=60&v=4)](https://appv2.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/7587031851) | [![Google](https://avatars.githubusercontent.com/u/2810941?s=60&v=4)](https://appv2.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/7576989995) | [![DataDog](https://avatars.githubusercontent.com/u/365230?s=60&v=4)](https://appv2.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/7446169664) | [![Intel](https://avatars.githubusercontent.com/u/17888862?s=60&v=4)](https://appv2.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/7590975903) | [![Kubernetes](https://avatars.githubusercontent.com/u/36015203?s=60&v=4)](https://appv2.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/7591172950) | [![Node.js](https://avatars.githubusercontent.com/u/9950313?s=60&v=4)](https://appv2.stepsecurity.io/github/nodejs/node/actions/runs/7591405720) | [![AWS](https://avatars.githubusercontent.com/u/2232217?s=60&v=4)](https://appv2.stepsecurity.io/github/aws/aperf/actions/runs/7631366761) |
| [![CISA](https://avatars.githubusercontent.com/u/18539691?s=60&v=4)](https://app.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/9947319332?jobid=27479776091&tab=network-events) | [![Microsoft](https://avatars.githubusercontent.com/u/6154722?s=60&v=4)](https://app.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/7587031851) | [![Google](https://avatars.githubusercontent.com/u/2810941?s=60&v=4)](https://app.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/7576989995) | [![DataDog](https://avatars.githubusercontent.com/u/365230?s=60&v=4)](https://app.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/7446169664) | [![Intel](https://avatars.githubusercontent.com/u/17888862?s=60&v=4)](https://app.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/7590975903) | [![Kubernetes](https://avatars.githubusercontent.com/u/36015203?s=60&v=4)](https://app.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/7591172950) | [![Node.js](https://avatars.githubusercontent.com/u/9950313?s=60&v=4)](https://app.stepsecurity.io/github/nodejs/node/actions/runs/7591405720) | [![AWS](https://avatars.githubusercontent.com/u/2232217?s=60&v=4)](https://app.stepsecurity.io/github/aws/aperf/actions/runs/7631366761) |
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **CISA**<br>[Explore](https://appv2.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/9947319332?jobid=27479776091&tab=network-events) | **Microsoft**<br>[Explore](https://appv2.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/7587031851) | **Google**<br>[Explore](https://appv2.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/7576989995) | **DataDog**<br>[Explore](https://appv2.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/7446169664) | **Intel**<br>[Explore](https://appv2.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/7590975903) | **Kubernetes**<br>[Explore](https://appv2.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/7591172950) | **Node.js**<br>[Explore](https://appv2.stepsecurity.io/github/nodejs/node/actions/runs/7591405720) | **AWS**<br>[Explore](https://appv2.stepsecurity.io/github/aws/aperf/actions/runs/7631366761) |
| **CISA**<br>[Explore](https://app.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/9947319332?jobid=27479776091&tab=network-events) | **Microsoft**<br>[Explore](https://app.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/7587031851) | **Google**<br>[Explore](https://app.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/7576989995) | **DataDog**<br>[Explore](https://app.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/7446169664) | **Intel**<br>[Explore](https://app.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/7590975903) | **Kubernetes**<br>[Explore](https://app.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/7591172950) | **Node.js**<br>[Explore](https://app.stepsecurity.io/github/nodejs/node/actions/runs/7591405720) | **AWS**<br>[Explore](https://app.stepsecurity.io/github/aws/aperf/actions/runs/7631366761) |
### Case Studies
### Enterprise Case Studies
- [Harden-Runner Detects CI/CD Supply Chain Attack in Google’s Open-Source Project Flank](https://www.stepsecurity.io/case-studies/flank)
- [StepSecurity Detects CI/CD Supply Chain Attack in Microsoft’s Open-Source Project Azure Karpenter Provider in Real-Time](https://www.stepsecurity.io/case-studies/azure-karpenter-provider)
- [How Coveo Strengthened GitHub Actions Security with StepSecurity](https://www.stepsecurity.io/case-studies/coveo)
- [Hashgraph Achieves Comprehensive CI/CD Security Without Compromising Development Speed](https://www.stepsecurity.io/case-studies/hashgraph)
- [Chainguard Secures GitHub Actions with StepSecurity](https://www.stepsecurity.io/case-studies/chainguard)
- [Kapiche secures their GitHub Actions software supply chain with Harden-Runner](https://www.stepsecurity.io/case-studies/kapiche)
- [Arcjet Enhances CI/CD Security with Harden-Runner](https://www.stepsecurity.io/case-studies/arcjet)
---
## Environment Compatibility Matrix
Harden-Runner is designed to work seamlessly across a variety of runner environments, providing consistent security insights and protections regardless of where your workflows execute. For self-hosted runners, audit mode is deployed directly to the runner infrastructure without requiring any changes to your existing workflows. For more details, refer to the [official documentation](https://docs.stepsecurity.io/harden-runner).
| Environment Type | Compatibility | Audit Mode Deployment | Workflow Changes for Audit Mode |
|------------------|---------------|--------------------------|-------------------|
| GitHub-hosted runners | ✅ Full support | Add Harden-Runner Action to workflow | Yes |
| Self-hosted VM runners | ✅ Full support | Include agent in runner image | No |
| Self-hosted bare-metal runners | ✅ Full support | Install agent as a service | No |
| Actions Runner Controller (ARC) | ✅ Full support | Deploy as DaemonSet | No |
| RunsOn Runners | ✅ Full support | Pre-integrated | No |
## How It Works
Want to know the technical details? Dive into the architecture of Harden-Runner and its integrations for GitHub-hosted and self-hosted runners in our [How Harden-Runner Works Documentation](docs/how-it-works.md).
+5 -1
View File
@@ -17,7 +17,11 @@ inputs:
required: false
default: "false"
disable-sudo:
description: "Disable sudo access for the runner account"
description: "Disable sudo access for the runner account. Note: This parameter will be deprecated in the future. Please use disable-sudo-and-containers instead."
required: false
default: "false"
disable-sudo-and-containers:
description: "Disable sudo and container access for the runner account"
required: false
default: "false"
disable-file-monitoring:
+29799 -782
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+29824 -789
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+62924 -48976
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -3,12 +3,12 @@
### GitHub-Hosted Runners
* Only Ubuntu VM is supported. Windows and MacOS GitHub-hosted runners are not supported. There is a discussion about that [here](https://github.com/step-security/harden-runner/discussions/121).
* Harden-Runner is not supported when [job is run in a container](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container) as it needs sudo access on the Ubuntu VM to run. It can be used to monitor jobs that use containers to run steps. The limitation is if the entire job is run in a container. That is not common for GitHub Actions workflows, as most of them run directly on `ubuntu-latest`. Note: This is not a limitation for Self-Hosted runners.
* Harden-Runner is not supported when [job is run in a container](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container) with built-in labels such as `ubuntu-latest`, as it needs sudo access on the Ubuntu VM to run. The limitation is if the entire job is run in a container. However, such jobs can be monitored when using custom VM images with GitHub-hosted runners. This is also not a limitation for Self-Hosted runners.
### Self-Hosted Actions Runner Controller (ARC) Runners
* Since ARC Harden Runner uses eBPF, only Linux jobs are supported. Windows and MacOS jobs are not supported.
### Self-Hosted VM Runners (e.g. on EC2)
### Self-Hosted VM (e.g. on EC2) and Bare-metal Runners
* Only Ubuntu VM is supported. Windows and MacOS jobs are not supported.
* Only Linux jobs are supported. Windows and MacOS jobs are not supported.
Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

+11
View File
@@ -0,0 +1,11 @@
[[IgnoredVulns]]
id = "GHSA-h5c3-5r3r-rr8q"
reason = "Untrusted headers are not processed"
[[IgnoredVulns]]
id = "GHSA-rmvr-2pp2-xj38"
reason = "Untrusted headers are not processed"
[[IgnoredVulns]]
id = "GHSA-xx4v-prfh-6cgc"
reason = "Untrusted headers are not processed"
+1285 -931
View File
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -23,12 +23,13 @@
},
"homepage": "https://github.com/step-security/harden-runner#readme",
"dependencies": {
"@actions/cache": "^3.1.4",
"@actions/cache": "^4.0.0",
"@actions/core": "^1.5.0",
"@actions/exec": "^1.1.0",
"@actions/github": "^5.0.0",
"@actions/github": "^6.0.1",
"@actions/http-client": "^2.0.1",
"@actions/tool-cache": "^1.7.1",
"@babel/helpers": "^7.26.10",
"ansi-regex": ">=5.0.1",
"is-docker": "^3.0.0",
"node-fetch": ">=3.2.0",
@@ -39,7 +40,7 @@
"@types/node": "^16.9.0",
"@typescript-eslint/eslint-plugin": "^6.1.0",
"@typescript-eslint/parser": "^6.1.0",
"@vercel/ncc": "^0.30.0",
"@vercel/ncc": "^0.38.3",
"eslint": "^7.32.0",
"eslint-config-google": "^0.14.0",
"jest": "^29.3.1",
+2 -2
View File
@@ -1,9 +1,9 @@
import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
import { isARCRunner } from "./arc-runner";
it("should correctly recognize arc based runner", async () => {
process.env["GITHUB_ACTIONS_RUNNER_EXTRA_USER_AGENT"] =
"actions-runner-controller/2.0.1";
let isArc: boolean = await isArcRunner();
let isArc: boolean = await isARCRunner();
expect(isArc).toBe(true);
});
+16 -6
View File
@@ -2,7 +2,7 @@ import * as cp from "child_process";
import * as fs from "fs";
import path from "path";
export function isArcRunner(): boolean {
export function isARCRunner(): boolean {
const runnerUserAgent = process.env["GITHUB_ACTIONS_RUNNER_EXTRA_USER_AGENT"];
let isARC = false;
@@ -18,23 +18,33 @@ export function isArcRunner(): boolean {
function isSecondaryPod(): boolean {
const workDir = "/__w";
return fs.existsSync(workDir);
let hasKubeEnv = process.env["KUBERNETES_PORT"] !== undefined;
return fs.existsSync(workDir) && hasKubeEnv;
}
export function sendAllowedEndpoints(endpoints: string): void {
const startTime = Date.now();
const allowedEndpoints = endpoints.split(" "); // endpoints are space separated
for (const endpoint of allowedEndpoints) {
if (endpoint) {
let sent = 0;
for (let endpoint of allowedEndpoints) {
endpoint = endpoint.trim();
if (endpoint.length > 0) {
let encodedEndpoint = Buffer.from(endpoint).toString("base64");
let endpointPolicyStr = `step_policy_endpoint_${encodedEndpoint}`;
echo(endpointPolicyStr);
sent++;
}
}
if (allowedEndpoints.length > 0) {
applyPolicy(allowedEndpoints.length);
if (sent > 0) {
applyPolicy(sent);
}
const duration = Date.now() - startTime;
console.log(
`[harden-runner] sendAllowedEndpoints completed in ${duration}ms (sent ${sent} endpoints)`
);
}
function applyPolicy(count: number): void {
+3 -3
View File
@@ -4,11 +4,11 @@ import * as fs from "fs";
const CHECKSUMS = {
tls: {
amd64: "38e7ed97ced6fe0c1cf0fb5ee3b3d521dfe28d5ddf1cdca72d130c8d1b4a314e", // v1.4.2
arm64: "f67c80cc578c996d4f882c14fcdb63df57927d907cd22f1ec65f9fa940c08cf3",
amd64: "2a5be06ab620340f6957ddd180450caab414671c8b7da1996d8e2755c1cd49fa", // v1.7.9
arm64: "e9d0ccf3e4e62ba15ff208ef6e0afa0ad5e323c3dfc50527342f436a85e65a55",
},
non_tls: {
amd64: "a9f1842e3d7f3d38c143dbe8ffe1948e6c8173cd04da072d9f9d128bb400844a", // v0.13.7
amd64: "336093af8ebe969567b66fd035af3bd4f7e1c723ce680d6b4b5b2a1f79bc329e", // v0.14.2
},
};
+28 -7
View File
@@ -2,11 +2,18 @@ import * as fs from "fs";
import * as cp from "child_process";
import * as common from "./common";
import isDocker from "is-docker";
import { isArcRunner } from "./arc-runner";
import { isARCRunner } from "./arc-runner";
import { isGithubHosted } from "./tls-inspect";
import { context } from "@actions/github";
(async () => {
console.log("[harden-runner] post-step");
const customProperties = context?.payload?.repository?.custom_properties || {};
if (customProperties["skip-harden-runner"] === "true") {
console.log("Skipping harden-runner: custom property 'skip-harden-runner' is set to 'true'");
return;
}
if (process.platform !== "linux") {
console.log(common.UBUNTU_MESSAGE);
return;
@@ -16,7 +23,7 @@ import { isGithubHosted } from "./tls-inspect";
return;
}
if (isArcRunner()) {
if (isARCRunner()) {
console.log(`[!] ${common.ARC_RUNNER_MESSAGE}`);
return;
}
@@ -25,6 +32,10 @@ import { isGithubHosted } from "./tls-inspect";
return;
}
if (process.env.STATE_customVMImage === "true") {
return;
}
if (process.env.STATE_isTLS === "false" && process.arch === "arm64") {
return;
}
@@ -37,6 +48,11 @@ import { isGithubHosted } from "./tls-inspect";
return;
}
if (isGithubHosted() && fs.existsSync("/home/agent/post_event.json")) {
console.log("Post step already executed, skipping");
return;
}
fs.writeFileSync(
"/home/agent/post_event.json",
JSON.stringify({ event: "post" })
@@ -81,12 +97,17 @@ import { isGithubHosted } from "./tls-inspect";
}
var disable_sudo = process.env.STATE_disableSudo;
if (disable_sudo !== "true") {
var disable_sudo_and_containers = process.env.STATE_disableSudoAndContainers;
if (disable_sudo !== "true" && disable_sudo_and_containers !== "true") {
try {
var journalLog = cp.execSync("sudo journalctl -u agent.service --lines=1000", {
encoding: "utf8",
maxBuffer: 1024 * 1024 * 10 // 10MB buffer
});
var journalLog = cp.execSync(
"sudo journalctl -u agent.service --lines=1000",
{
encoding: "utf8",
maxBuffer: 1024 * 1024 * 10, // 10MB buffer
}
);
console.log("agent.service log:");
console.log(journalLog);
} catch (error) {
+30 -72
View File
@@ -1,6 +1,6 @@
import * as core from "@actions/core";
import * as fs from "fs";
import { STEPSECURITY_WEB_URL } from "./configs";
import { STEPSECURITY_API_URL, STEPSECURITY_WEB_URL } from "./configs";
export function printInfo(web_url) {
console.log(
@@ -59,14 +59,12 @@ export async function addSummary() {
return;
}
const web_url = STEPSECURITY_WEB_URL;
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
const log = "/home/agent/agent.log";
if (!fs.existsSync(log)) {
const correlation_id = process.env.STATE_correlation_id;
if (!correlation_id) {
return;
}
let needsSubscription = false;
try {
let data = fs.readFileSync("/home/agent/annotation.log", "utf8");
@@ -96,85 +94,45 @@ export async function addSummary() {
return;
}
const content = fs.readFileSync(log, "utf-8");
const lines = content.split("\n");
let tableEntries = [];
for (const line of lines) {
processLogLine(line, tableEntries);
}
if (tableEntries.length === 0) {
// Extract owner and repo from GITHUB_REPOSITORY (format: owner/repo)
const [owner, repo] = process.env["GITHUB_REPOSITORY"]?.split("/") || [];
const run_id = process.env["GITHUB_RUN_ID"];
if (!owner || !repo || !run_id || !correlation_id) {
return;
}
const insightsRow = `<p><b><a href="${insights_url}">📄 View Full Report</a></b></p>`;
await core.summary.addSeparator().addRaw(`<h2>🛡 StepSecurity Report</h2>`);
tableEntries.sort((a, b) => {
if (a.status === "❌ Blocked" && b.status !== "❌ Blocked") {
return -1;
} else if (a.status !== "❌ Blocked" && b.status === "❌ Blocked") {
return 1;
} else {
return 0;
// Fetch job summary from API
const apiUrl = `${STEPSECURITY_API_URL}/github/${owner}/${repo}/actions/runs/${run_id}/correlation/${correlation_id}/job-markdown-summary`;
try {
const response = await fetch(apiUrl);
if (!response.ok) {
console.error(`Failed to fetch job summary: ${response.status} ${response.statusText}`);
return;
}
});
tableEntries = tableEntries.slice(0, 3);
await core.summary.addRaw(`
<blockquote>
<p>Preview of the outbound network calls during this workflow run.</p></blockquote>
<h3>Network Calls</h3>
<table>
<thead>
<tr>
<th>Process</th>
<th>Destination</th>
<th>Status</th>
</tr>
</thead>
<tbody>
${tableEntries
.map(
(entry) => `<tr>
<td><code>${entry.process}</code></td>
<td>${entry.domain.replace(/\.$/, "")}</td>
<td>${entry.status}</td>
</tr>`
)
.join("")}
<tr>
<td><code>...</code></td>
<td><code>...</code></td>
<td><code>...</code></td>
</tr>
</tbody>
</table>
${insightsRow}
`);
await core.summary
.addRaw(
`<p><i>Markdown generated by the <a href="https://github.com/step-security/harden-runner">Harden-Runner GitHub Action</a>.</i></p>`
)
.addSeparator()
.write();
const markdownSummary = await response.text();
// Render the markdown summary using core.summary.addRaw
await core.summary.addRaw(markdownSummary).write();
return;
} catch (error) {
console.error(`Error fetching job summary: ${error}`);
return;
}
}
export const STATUS_HARDEN_RUNNER_UNAVAILABLE = "409";
export const CONTAINER_MESSAGE =
"This job is running in a container. Harden Runner does not run in a container as it needs sudo access to run. This job will not be monitored.";
"This job is running in a container. Such jobs can be monitored by installing Harden Runner in a custom VM image for GitHub-hosted runners.";
export const UBUNTU_MESSAGE =
"This job is not running in a GitHub Actions Hosted Runner Ubuntu VM. Harden Runner is only supported on Ubuntu VM. This job will not be monitored.";
export const SELF_HOSTED_NO_AGENT_MESSAGE =
"This job is running on a self-hosted runner, but the runner does not have Harden-Runner installed. This job will not be monitored.";
export const SELF_HOSTED_RUNNER_MESSAGE =
"This job is running on a self-hosted runner.";
export const HARDEN_RUNNER_UNAVAILABLE_MESSAGE =
"Sorry, we are currently experiencing issues with the Harden Runner installation process. It is currently unavailable.";
+7
View File
@@ -3,9 +3,16 @@ import * as core from "@actions/core";
import isDocker from "is-docker";
import { STEPSECURITY_WEB_URL } from "./configs";
import { isGithubHosted } from "./tls-inspect";
import { context } from "@actions/github";
(async () => {
console.log("[harden-runner] main-step");
const customProperties = context?.payload?.repository?.custom_properties || {};
if (customProperties["skip-harden-runner"] === "true") {
console.log("Skipping harden-runner: custom property 'skip-harden-runner' is set to 'true'");
return;
}
if (process.platform !== "linux") {
console.log(common.UBUNTU_MESSAGE);
return;
+4 -2
View File
@@ -25,7 +25,9 @@ export async function installAgent(
if (isTLS) {
downloadPath = await tc.downloadTool(
`https://packages.stepsecurity.io/github-hosted/harden-runner_1.4.2_linux_${variant}.tar.gz`
`https://github.com/step-security/agent-ebpf/releases/download/v1.7.9/harden-runner_1.7.9_linux_${variant}.tar.gz`,
undefined,
auth
);
} else {
if (variant === "arm64") {
@@ -33,7 +35,7 @@ export async function installAgent(
return false;
}
downloadPath = await tc.downloadTool(
"https://github.com/step-security/agent/releases/download/v0.13.7/agent_0.13.7_linux_amd64.tar.gz",
"https://github.com/step-security/agent/releases/download/v0.14.2/agent_0.14.2_linux_amd64.tar.gz",
undefined,
auth
);
+2
View File
@@ -8,6 +8,7 @@ export interface Configuration {
egress_policy: string;
disable_telemetry: boolean;
disable_sudo: boolean;
disable_sudo_and_containers: boolean;
disable_file_monitoring: boolean;
is_github_hosted: boolean;
private: string;
@@ -20,6 +21,7 @@ export interface PolicyResponse {
policyName?: string;
allowed_endpoints?: string[];
disable_sudo?: boolean;
disable_sudo_and_containers?: boolean;
disable_file_monitoring?: boolean;
disable_telemetry?: boolean;
egress_policy?: string;
+2
View File
@@ -36,6 +36,7 @@ test("merge configs", async () => {
egress_policy: "audit",
disable_telemetry: false,
disable_sudo: false,
disable_sudo_and_containers: false,
disable_file_monitoring: false,
private: "true",
is_github_hosted: true,
@@ -62,6 +63,7 @@ test("merge configs", async () => {
egress_policy: "audit",
disable_telemetry: false,
disable_sudo: false,
disable_sudo_and_containers: false,
disable_file_monitoring: false,
private: "true",
is_github_hosted: true,
+11 -2
View File
@@ -39,7 +39,12 @@ export async function fetchPolicy(
}
if (response === undefined && err !== undefined) {
throw new Error(`[Policy Fetch] ${err}`);
// Preserve the original error's statusCode if it exists
const error = new Error(`[Policy Fetch] ${err}`);
if (err.statusCode !== undefined) {
(error as any).statusCode = err.statusCode;
}
throw error;
} else {
return response.result;
}
@@ -56,6 +61,10 @@ export function mergeConfigs(
localConfig.disable_sudo = remoteConfig.disable_sudo;
}
if (remoteConfig.disable_sudo_and_containers !== undefined) {
localConfig.disable_sudo_and_containers = remoteConfig.disable_sudo_and_containers;
}
if (remoteConfig.disable_file_monitoring !== undefined) {
localConfig.disable_file_monitoring = remoteConfig.disable_file_monitoring;
}
@@ -66,7 +75,7 @@ export function mergeConfigs(
return localConfig;
}
function sleep(ms) {
function sleep(ms: number) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
+138 -41
View File
@@ -19,8 +19,12 @@ import { Configuration, PolicyResponse } from "./interfaces";
import { fetchPolicy, mergeConfigs } from "./policy-utils";
import * as cache from "@actions/cache";
import { getCacheEntry } from "@actions/cache/lib/internal/cacheHttpClient";
import * as cacheTwirpClient from "@actions/cache/lib/internal/shared/cacheTwirpClient";
import { GetCacheEntryDownloadURLRequest } from "@actions/cache/lib/generated/results/api/v1/cache";
import { getCacheServiceVersion } from "@actions/cache/lib/internal/config";
import * as utils from "@actions/cache/lib/internal/cacheUtils";
import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
import { isARCRunner, sendAllowedEndpoints } from "./arc-runner";
import { STEPSECURITY_API_URL, STEPSECURITY_WEB_URL } from "./configs";
import { isGithubHosted, isTLSEnabled } from "./tls-inspect";
import { installAgent } from "./install-agent";
@@ -35,6 +39,12 @@ interface MonitorResponse {
try {
console.log("[harden-runner] pre-step");
const customProperties = context?.payload?.repository?.custom_properties || {};
if (customProperties["skip-harden-runner"] === "true") {
console.log("Skipping harden-runner: custom property 'skip-harden-runner' is set to 'true'");
return;
}
if (process.platform !== "linux") {
console.log(common.UBUNTU_MESSAGE);
return;
@@ -58,6 +68,9 @@ interface MonitorResponse {
egress_policy: core.getInput("egress-policy"),
disable_telemetry: core.getBooleanInput("disable-telemetry"),
disable_sudo: core.getBooleanInput("disable-sudo"),
disable_sudo_and_containers: core.getBooleanInput(
"disable-sudo-and-containers"
),
disable_file_monitoring: core.getBooleanInput("disable-file-monitoring"),
private: context?.payload?.repository?.private || false,
is_github_hosted: isGithubHosted(),
@@ -78,7 +91,18 @@ interface MonitorResponse {
confg = mergeConfigs(confg, result);
} catch (err) {
core.info(`[!] ${err}`);
core.setFailed(err);
// Only fail the job if ID token is not available
if (err.message && err.message.includes('Unable to get ACTIONS_ID_TOKEN_REQUEST')) {
core.setFailed('Policy store requires id-token write permission as it uses OIDC to fetch the policy from StepSecurity API. Please add "id-token: write" to your job permissions.');
} else {
// Handle different HTTP status codes
if (err.statusCode >= 400 && err.statusCode < 500) {
core.error('Policy not found');
} else {
core.error(`Unexpected error occurred: ${err}. Falling back to egress policy audit`);
confg.egress_policy = 'audit';
}
}
}
}
fs.appendFileSync(
@@ -88,6 +112,13 @@ interface MonitorResponse {
encoding: "utf8",
}
);
fs.appendFileSync(
process.env.GITHUB_STATE,
`disableSudoAndContainers=${confg.disable_sudo_and_containers}${EOL}`,
{
encoding: "utf8",
}
);
core.info(`[!] Current Configuration: \n${JSON.stringify(confg)}\n`);
if (confg.egress_policy !== "audit" && confg.egress_policy !== "block") {
@@ -114,28 +145,78 @@ interface MonitorResponse {
} catch (exception) {
console.log(exception);
}
try {
const compressionMethod: CompressionMethod =
await utils.getCompressionMethod();
const cacheFilePath = path.join(__dirname, "cache.txt");
core.info(`cacheFilePath ${cacheFilePath}`);
const cacheEntry: ArtifactCacheEntry = await getCacheEntry(
[cacheKey],
[cacheFilePath],
{
compressionMethod: compressionMethod,
const cacheServiceVersion: string = getCacheServiceVersion();
switch (cacheServiceVersion) {
case "v2":
core.info(`cache version: v2`);
try {
const cacheFilePath = path.join(__dirname, "cache.txt");
core.info(`cacheFilePath ${cacheFilePath}`);
const twirpClient = cacheTwirpClient.internalCacheTwirpClient();
const compressionMethod = await utils.getCompressionMethod();
const request: GetCacheEntryDownloadURLRequest = {
key: cacheKey,
restoreKeys: [],
version: utils.getCacheVersion(
[cacheFilePath],
compressionMethod,
false
),
};
const response = await twirpClient.GetCacheEntryDownloadURL(
request
);
const url = new URL(response.signedDownloadUrl);
core.info(
`Adding cacheHost: ${url.hostname}:443 to allowed-endpoints`
);
confg.allowed_endpoints += ` ${url.hostname}:443`;
} catch (e) {
core.info(`Unable to fetch cacheURL ${e}`);
if (confg.egress_policy === "block") {
core.info("Switching egress-policy to audit mode");
confg.egress_policy = "audit";
}
}
break;
case "v1":
core.info(`cache version: v1`);
try {
const compressionMethod: CompressionMethod =
await utils.getCompressionMethod();
const cacheFilePath = path.join(__dirname, "cache.txt");
core.info(`cacheFilePath ${cacheFilePath}`);
const cacheEntry: ArtifactCacheEntry = await getCacheEntry(
[cacheKey],
[cacheFilePath],
{
compressionMethod: compressionMethod,
}
);
const url = new URL(cacheEntry.archiveLocation);
core.info(
`Adding cacheHost: ${url.hostname}:443 to allowed-endpoints`
);
confg.allowed_endpoints += ` ${url.hostname}:443`;
} catch (exception) {
// some exception has occurred.
core.info(`Unable to fetch cacheURL ${exception}`);
if (confg.egress_policy === "block") {
core.info("Switching egress-policy to audit mode");
confg.egress_policy = "audit";
}
}
);
const url = new URL(cacheEntry.archiveLocation);
core.info(`Adding cacheHost: ${url.hostname}:443 to allowed-endpoints`);
confg.allowed_endpoints += ` ${url.hostname}:443`;
} catch (exception) {
// some exception has occurred.
core.info(`Unable to fetch cacheURL`);
if (confg.egress_policy === "block") {
core.info("Switching egress-policy to audit mode");
confg.egress_policy = "audit";
}
}
}
@@ -143,7 +224,7 @@ interface MonitorResponse {
common.printInfo(web_url);
}
if (isArcRunner()) {
if (isARCRunner()) {
console.log(`[!] ${common.ARC_RUNNER_MESSAGE}`);
if (confg.egress_policy === "block") {
sendAllowedEndpoints(confg.allowed_endpoints);
@@ -158,28 +239,37 @@ interface MonitorResponse {
fs.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${EOL}`, {
encoding: "utf8",
});
if (!fs.existsSync("/home/agent/agent")) {
core.info(common.SELF_HOSTED_NO_AGENT_MESSAGE);
return;
}
if (confg.egress_policy === "block") {
try {
if (process.env.USER) {
chownForFolder(process.env.USER, "/home/agent");
}
const confgStr = JSON.stringify(confg);
fs.writeFileSync("/home/agent/block_event.json", confgStr);
await sleep(5000);
} catch (error) {
core.info(`[!] Unable to write block_event.json: ${error}`);
}
core.info(common.SELF_HOSTED_RUNNER_MESSAGE);
if (confg.egress_policy === "block") {
sendAllowedEndpoints(confg.allowed_endpoints);
await sleep(5000);
}
return;
}
if (isGithubHosted() && process.env.STEP_SECURITY_HARDEN_RUNNER === "true") {
fs.appendFileSync(process.env.GITHUB_STATE, `customVMImage=true${EOL}`, {
encoding: "utf8",
});
core.info("This job is running on a custom VM image with Harden Runner installed.");
if (confg.egress_policy === "block") {
sendAllowedEndpoints(confg.allowed_endpoints);
await sleep(5000);
}
return;
}
if (isGithubHosted() && fs.existsSync("/home/agent/agent.status")) {
console.log("Agent already installed, skipping installation");
return;
}
let _http = new httpm.HttpClient();
let statusCode;
let statusCode: number | undefined;
_http.requestOptions = { socketTimeout: 3 * 1000 };
let addSummary = "false";
try {
@@ -217,6 +307,13 @@ interface MonitorResponse {
encoding: "utf8",
}
);
fs.appendFileSync(
process.env.GITHUB_STATE,
`correlation_id=${correlation_id}${EOL}`,
{
encoding: "utf8",
}
);
console.log(`Step Security Job Correlation ID: ${correlation_id}`);
if (String(statusCode) === common.STATUS_HARDEN_RUNNER_UNAVAILABLE) {
@@ -265,7 +362,7 @@ interface MonitorResponse {
process.exit(0);
})();
export function sleep(ms) {
export function sleep(ms: number) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});