mirror of
https://github.com/step-security/harden-runner
synced 2026-08-09 13:11:02 +00:00
Compare commits
30
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9462746bdb | ||
|
|
20cf305ff2 | ||
|
|
c51e8eeb6c | ||
|
|
e152b90204 | ||
|
|
ee1faec052 | ||
|
|
1dc7c17646 | ||
|
|
df199fb7be | ||
|
|
03d096a772 | ||
|
|
40901073af | ||
|
|
95d9a5deda | ||
|
|
87e429d3fb | ||
|
|
ef891c3a30 | ||
|
|
1fa8c8a8b1 | ||
|
|
92c522aaa6 | ||
|
|
4719ad5578 | ||
|
|
4fde639ab4 | ||
|
|
f682f2f2d0 | ||
|
|
f4a75cfd61 | ||
|
|
95503d076c | ||
|
|
4b250a0739 | ||
|
|
5b0ab6abcf | ||
|
|
d11f2c1d65 | ||
|
|
b3fc98e4df | ||
|
|
92fc5d4bf7 | ||
|
|
b61b0a4938 | ||
|
|
e3d3f2baea | ||
|
|
646ac01e72 | ||
|
|
7bc18df383 | ||
|
|
17d38b322b | ||
|
|
ec9f2d5744 |
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -44,3 +44,32 @@ jobs:
|
||||
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
|
||||
|
||||
@@ -24,12 +24,14 @@ StepSecurity Harden-Runner addresses this gap by providing security monitoring t
|
||||
|
||||
- [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 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)
|
||||
- [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 **a 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:
|
||||
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
|
||||
@@ -135,7 +137,7 @@ Explore the full feature set in the [Features Documentation](https://docs.stepse
|
||||
|
||||
## Trusted By and Case Studies
|
||||
|
||||
Harden-Runner is trusted by over 6000 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
|
||||
|
||||
|
||||
Vendored
+6414
-2139
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+6421
-2137
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+14976
-17428
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -3,7 +3,7 @@
|
||||
### 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
|
||||
|
||||
|
||||
Generated
+546
-259
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -26,7 +26,7 @@
|
||||
"@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",
|
||||
@@ -40,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
@@ -4,8 +4,8 @@ import * as fs from "fs";
|
||||
|
||||
const CHECKSUMS = {
|
||||
tls: {
|
||||
amd64: "5c02a40df6e2c926c92ffc6bf02ca8a301649d44541ca57e40a87948fb0d3f2e", // v1.6.18
|
||||
arm64: "b953784a468343c44a1a3ef4ec984c738a9a1e84aaf6932a2bb9dbf7ac7eab29",
|
||||
amd64: "2a5be06ab620340f6957ddd180450caab414671c8b7da1996d8e2755c1cd49fa", // v1.7.9
|
||||
arm64: "e9d0ccf3e4e62ba15ff208ef6e0afa0ad5e323c3dfc50527342f436a85e65a55",
|
||||
},
|
||||
non_tls: {
|
||||
amd64: "336093af8ebe969567b66fd035af3bd4f7e1c723ce680d6b4b5b2a1f79bc329e", // v0.14.2
|
||||
|
||||
@@ -4,9 +4,16 @@ import * as common from "./common";
|
||||
import isDocker from "is-docker";
|
||||
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;
|
||||
@@ -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" })
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ export async function addSummary() {
|
||||
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.";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -25,7 +25,9 @@ export async function installAgent(
|
||||
|
||||
if (isTLS) {
|
||||
downloadPath = await tc.downloadTool(
|
||||
`https://packages.stepsecurity.io/github-hosted/harden-runner_1.6.18_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") {
|
||||
|
||||
+7
-2
@@ -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;
|
||||
}
|
||||
@@ -70,7 +75,7 @@ export function mergeConfigs(
|
||||
return localConfig;
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
function sleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
|
||||
+39
-3
@@ -39,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;
|
||||
@@ -85,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(
|
||||
@@ -232,8 +249,27 @@ interface MonitorResponse {
|
||||
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 {
|
||||
@@ -326,7 +362,7 @@ interface MonitorResponse {
|
||||
process.exit(0);
|
||||
})();
|
||||
|
||||
export function sleep(ms) {
|
||||
export function sleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user