mirror of
https://github.com/step-security/harden-runner
synced 2026-08-09 13:11:02 +00:00
Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35cd77bcf6 | ||
|
|
bb6dbef4bf | ||
|
|
98f73c5a0d | ||
|
|
54193c17a4 | ||
|
|
d22dd481ce | ||
|
|
0ff09412fb | ||
|
|
a3c333d110 | ||
|
|
bf94c00d6b | ||
|
|
514522c5e4 | ||
|
|
bf7454d06d |
@@ -118,6 +118,7 @@ Harden-Runner offers a comprehensive suite of features to enhance the security o
|
||||
- **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.
|
||||
- **Global Block List:** Block known-malicious domains and IP addresses tied to active supply chain attacks, maintained by StepSecurity's 24x7 SOC. No configuration required, new indicators apply automatically without an action version bump, and it is enforced even in `egress-policy: audit` mode.
|
||||
- **Detect Modification of Source Code:** Monitor and alert on unauthorized changes to your source code during the CI/CD pipeline.
|
||||
|
||||
### Enterprise (Paid)
|
||||
|
||||
Vendored
+23
@@ -31880,9 +31880,12 @@ var lib_core = __nccwpck_require__(7484);
|
||||
var external_child_process_ = __nccwpck_require__(5317);
|
||||
// EXTERNAL MODULE: external "fs"
|
||||
var external_fs_ = __nccwpck_require__(9896);
|
||||
// EXTERNAL MODULE: external "os"
|
||||
var external_os_ = __nccwpck_require__(857);
|
||||
;// CONCATENATED MODULE: ./src/utils.ts
|
||||
|
||||
|
||||
|
||||
function isPlatformSupported(platform) {
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
@@ -31893,7 +31896,25 @@ function isPlatformSupported(platform) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Resolves the user the runner process is executing as. Some runner
|
||||
// environments (e.g. AWS CodeBuild-hosted runners) do not set the USER
|
||||
// environment variable.
|
||||
function getRunnerUser() {
|
||||
if (process.env.USER) {
|
||||
return process.env.USER;
|
||||
}
|
||||
try {
|
||||
return os.userInfo().username;
|
||||
}
|
||||
catch (_a) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
function chownForFolder(newOwner, target) {
|
||||
if (!newOwner) {
|
||||
console.log(`Unable to determine runner user; skipping chown of ${target}`);
|
||||
return;
|
||||
}
|
||||
let cmd = "sudo";
|
||||
let args = ["chown", "-R", newOwner, target];
|
||||
cp.execFileSync(cmd, args);
|
||||
@@ -31921,6 +31942,8 @@ function detectThirdPartyRunnerProvider() {
|
||||
return "namespace";
|
||||
if (process.env["BITRISE_IO"])
|
||||
return "bitrise";
|
||||
if (process.env["CODEBUILD_RUNNER_TYPE"] === "GITHUB")
|
||||
return "codebuild";
|
||||
const runnerName = (_a = process.env["RUNNER_NAME"]) !== null && _a !== void 0 ? _a : "";
|
||||
if (runnerName.startsWith("warp-"))
|
||||
return "warp";
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+23
@@ -31886,9 +31886,12 @@ const STEPSECURITY_WEB_URL = "https://app.stepsecurity.io";
|
||||
|
||||
// EXTERNAL MODULE: external "child_process"
|
||||
var external_child_process_ = __nccwpck_require__(5317);
|
||||
// EXTERNAL MODULE: external "os"
|
||||
var external_os_ = __nccwpck_require__(857);
|
||||
;// CONCATENATED MODULE: ./src/utils.ts
|
||||
|
||||
|
||||
|
||||
function isPlatformSupported(platform) {
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
@@ -31899,7 +31902,25 @@ function isPlatformSupported(platform) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Resolves the user the runner process is executing as. Some runner
|
||||
// environments (e.g. AWS CodeBuild-hosted runners) do not set the USER
|
||||
// environment variable.
|
||||
function getRunnerUser() {
|
||||
if (process.env.USER) {
|
||||
return process.env.USER;
|
||||
}
|
||||
try {
|
||||
return os.userInfo().username;
|
||||
}
|
||||
catch (_a) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
function chownForFolder(newOwner, target) {
|
||||
if (!newOwner) {
|
||||
console.log(`Unable to determine runner user; skipping chown of ${target}`);
|
||||
return;
|
||||
}
|
||||
let cmd = "sudo";
|
||||
let args = ["chown", "-R", newOwner, target];
|
||||
cp.execFileSync(cmd, args);
|
||||
@@ -31927,6 +31948,8 @@ function detectThirdPartyRunnerProvider() {
|
||||
return "namespace";
|
||||
if (process.env["BITRISE_IO"])
|
||||
return "bitrise";
|
||||
if (process.env["CODEBUILD_RUNNER_TYPE"] === "GITHUB")
|
||||
return "codebuild";
|
||||
const runnerName = (_a = process.env["RUNNER_NAME"]) !== null && _a !== void 0 ? _a : "";
|
||||
if (runnerName.startsWith("warp-"))
|
||||
return "warp";
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+33
-12
@@ -85078,9 +85078,12 @@ const validate = dist/* validate */.tf;
|
||||
const stringify = dist/* stringify */.As;
|
||||
const parse = dist/* parse */.qg;
|
||||
|
||||
// EXTERNAL MODULE: external "os"
|
||||
var external_os_ = __nccwpck_require__(857);
|
||||
;// CONCATENATED MODULE: ./src/utils.ts
|
||||
|
||||
|
||||
|
||||
function isPlatformSupported(platform) {
|
||||
switch (platform) {
|
||||
case "linux":
|
||||
@@ -85091,7 +85094,25 @@ function isPlatformSupported(platform) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Resolves the user the runner process is executing as. Some runner
|
||||
// environments (e.g. AWS CodeBuild-hosted runners) do not set the USER
|
||||
// environment variable.
|
||||
function getRunnerUser() {
|
||||
if (process.env.USER) {
|
||||
return process.env.USER;
|
||||
}
|
||||
try {
|
||||
return external_os_.userInfo().username;
|
||||
}
|
||||
catch (_a) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
function chownForFolder(newOwner, target) {
|
||||
if (!newOwner) {
|
||||
console.log(`Unable to determine runner user; skipping chown of ${target}`);
|
||||
return;
|
||||
}
|
||||
let cmd = "sudo";
|
||||
let args = ["chown", "-R", newOwner, target];
|
||||
external_child_process_.execFileSync(cmd, args);
|
||||
@@ -85119,6 +85140,8 @@ function detectThirdPartyRunnerProvider() {
|
||||
return "namespace";
|
||||
if (process.env["BITRISE_IO"])
|
||||
return "bitrise";
|
||||
if (process.env["CODEBUILD_RUNNER_TYPE"] === "GITHUB")
|
||||
return "codebuild";
|
||||
const runnerName = (_a = process.env["RUNNER_NAME"]) !== null && _a !== void 0 ? _a : "";
|
||||
if (runnerName.startsWith("warp-"))
|
||||
return "warp";
|
||||
@@ -85285,8 +85308,6 @@ function isDocker() {
|
||||
|
||||
// EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js
|
||||
var github = __nccwpck_require__(3228);
|
||||
// EXTERNAL MODULE: external "os"
|
||||
var external_os_ = __nccwpck_require__(857);
|
||||
;// CONCATENATED MODULE: ./src/cache.ts
|
||||
const cacheKey = "harden-runner-cacheKey";
|
||||
const cacheFile = "/home/agent/cache.txt";
|
||||
@@ -85543,15 +85564,15 @@ var external_crypto_ = __nccwpck_require__(6982);
|
||||
|
||||
const CHECKSUMS = {
|
||||
tls: {
|
||||
amd64: "a54c4305b5665ba54bfdc46eb32aee1758699b994550ca3658d698367cc96a3f", // v1.8.12
|
||||
arm64: "3f401d508e1427b9ba205681d5abecde3b4a0f0a18542d198b6dc14cadd93ab5", // v1.8.12
|
||||
amd64: "47c42675bce38c6ab7c4dcba90f009c8567f491bc71ecf492f4ef1876c300700", // v1.8.14
|
||||
arm64: "9aed5e0a4a97ad019f943087dee6b7bd6ace340b06c6faba5615927b9a50a7d4", // v1.8.14
|
||||
},
|
||||
non_tls: {
|
||||
amd64: "4b14d8a3a5fbcef95af55e0c54d3bee6f44da802878c10289a4ca0b79b6d0237", // v0.16.2
|
||||
},
|
||||
bravo: {
|
||||
amd64: "c986d0a19637325c9a8d4a331a6c4ed047e4cddb798f56b641d0e66f8bf9b1b2", // v1.8.12
|
||||
arm64: "5c3df17f82e317c8b288dfbbcee449c2a24a80deeeb3416dccabd0a61982c676", // v1.8.12
|
||||
amd64: "83d8189320edc26085e3fefc3682db231e778b563d2f22bc7bf7c339a9562aab", // v1.8.14
|
||||
arm64: "1d9813cdf3684339c542f9342805a173c457af1860b98da66b7672918e121434", // v1.8.14
|
||||
},
|
||||
darwin: "2990f0390d2760fa6262a3830060b6db1233f16a1410ffe1ed2bf13dfda80c38", // v0.0.6
|
||||
windows: {
|
||||
@@ -85624,7 +85645,7 @@ function installAgent(isTLS, configStr) {
|
||||
encoding: "utf8",
|
||||
});
|
||||
if (isTLS) {
|
||||
downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.8.12/harden-runner_1.8.12_linux_${variant}.tar.gz`, undefined, auth);
|
||||
downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.8.14/harden-runner_1.8.14_linux_${variant}.tar.gz`, undefined, auth);
|
||||
}
|
||||
else {
|
||||
if (variant === "arm64") {
|
||||
@@ -85659,7 +85680,7 @@ function installAgentBravo(configStr) {
|
||||
const token = lib_core.getInput("token", { required: true });
|
||||
const auth = `token ${token}`;
|
||||
const variant = process.arch === "x64" ? "amd64" : "arm64";
|
||||
const downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.8.12/harden-runner-bravo_1.8.12_linux_${variant}.tar.gz`, undefined, auth);
|
||||
const downloadPath = yield tool_cache.downloadTool(`https://github.com/step-security/agent-ebpf/releases/download/v1.8.14/harden-runner-bravo_1.8.14_linux_${variant}.tar.gz`, undefined, auth);
|
||||
if (!verifyChecksum(downloadPath, true, variant, "linux", "bravo")) {
|
||||
return false;
|
||||
}
|
||||
@@ -85706,7 +85727,7 @@ function installMacosAgent(configStr) {
|
||||
// Create working directory
|
||||
lib_core.info("Creating /opt/step-security directory...");
|
||||
external_child_process_.execSync("sudo mkdir -p /opt/step-security");
|
||||
chownForFolder(process.env.USER, "/opt/step-security");
|
||||
chownForFolder(getRunnerUser(), "/opt/step-security");
|
||||
lib_core.info("✓ Successfully created /opt/step-security directory");
|
||||
// Create agent configuration file
|
||||
lib_core.info("Creating agent.json");
|
||||
@@ -86208,7 +86229,7 @@ process.on("unhandledRejection", (reason) => {
|
||||
statusFile = "/home/agent/agent.status";
|
||||
logFile = "/home/agent/agent.log";
|
||||
external_child_process_.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
chownForFolder(getRunnerUser(), "/home/agent");
|
||||
let isTLS = yield isTLSEnabled(github.context.repo.owner);
|
||||
agentInstalled = yield installAgent(isTLS, configStr);
|
||||
break;
|
||||
@@ -86319,7 +86340,7 @@ function installAgentForSelfHosted(owner, confg) {
|
||||
};
|
||||
const selfHostedConfigStr = JSON.stringify(selfHostedConfig);
|
||||
external_child_process_.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
chownForFolder(getRunnerUser(), "/home/agent");
|
||||
const agentInstalled = yield installAgent(isTLS, selfHostedConfigStr);
|
||||
if (agentInstalled) {
|
||||
const statusFile = "/home/agent/agent.status";
|
||||
@@ -86361,7 +86382,7 @@ function installAgentForBravo(owner, bravoConfigStr) {
|
||||
return;
|
||||
}
|
||||
external_child_process_.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
chownForFolder(getRunnerUser(), "/home/agent");
|
||||
yield installAgentBravo(bravoConfigStr);
|
||||
}
|
||||
catch (error) {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+4
-4
@@ -4,15 +4,15 @@ import * as fs from "fs";
|
||||
|
||||
export const CHECKSUMS = {
|
||||
tls: {
|
||||
amd64: "a54c4305b5665ba54bfdc46eb32aee1758699b994550ca3658d698367cc96a3f", // v1.8.12
|
||||
arm64: "3f401d508e1427b9ba205681d5abecde3b4a0f0a18542d198b6dc14cadd93ab5", // v1.8.12
|
||||
amd64: "47c42675bce38c6ab7c4dcba90f009c8567f491bc71ecf492f4ef1876c300700", // v1.8.14
|
||||
arm64: "9aed5e0a4a97ad019f943087dee6b7bd6ace340b06c6faba5615927b9a50a7d4", // v1.8.14
|
||||
},
|
||||
non_tls: {
|
||||
amd64: "4b14d8a3a5fbcef95af55e0c54d3bee6f44da802878c10289a4ca0b79b6d0237", // v0.16.2
|
||||
},
|
||||
bravo: {
|
||||
amd64: "c986d0a19637325c9a8d4a331a6c4ed047e4cddb798f56b641d0e66f8bf9b1b2", // v1.8.12
|
||||
arm64: "5c3df17f82e317c8b288dfbbcee449c2a24a80deeeb3416dccabd0a61982c676", // v1.8.12
|
||||
amd64: "83d8189320edc26085e3fefc3682db231e778b563d2f22bc7bf7c339a9562aab", // v1.8.14
|
||||
arm64: "1d9813cdf3684339c542f9342805a173c457af1860b98da66b7672918e121434", // v1.8.14
|
||||
},
|
||||
darwin: "2990f0390d2760fa6262a3830060b6db1233f16a1410ffe1ed2bf13dfda80c38", // v0.0.6
|
||||
windows: {
|
||||
|
||||
@@ -6,7 +6,7 @@ import * as fs from "fs";
|
||||
import { verifyChecksum } from "./checksum";
|
||||
import { EOL } from "os";
|
||||
import { ARM64_RUNNER_MESSAGE, ARM64_WINDOWS_RUNNER_MESSAGE } from "./common";
|
||||
import { chownForFolder } from "./utils";
|
||||
import { chownForFolder, getRunnerUser } from "./utils";
|
||||
|
||||
export async function installAgent(
|
||||
isTLS: boolean,
|
||||
@@ -26,7 +26,7 @@ export async function installAgent(
|
||||
|
||||
if (isTLS) {
|
||||
downloadPath = await tc.downloadTool(
|
||||
`https://github.com/step-security/agent-ebpf/releases/download/v1.8.12/harden-runner_1.8.12_linux_${variant}.tar.gz`,
|
||||
`https://github.com/step-security/agent-ebpf/releases/download/v1.8.14/harden-runner_1.8.14_linux_${variant}.tar.gz`,
|
||||
undefined,
|
||||
auth
|
||||
);
|
||||
@@ -76,7 +76,7 @@ export async function installAgentBravo(configStr: string): Promise<boolean> {
|
||||
|
||||
const variant = process.arch === "x64" ? "amd64" : "arm64";
|
||||
const downloadPath = await tc.downloadTool(
|
||||
`https://github.com/step-security/agent-ebpf/releases/download/v1.8.12/harden-runner-bravo_1.8.12_linux_${variant}.tar.gz`,
|
||||
`https://github.com/step-security/agent-ebpf/releases/download/v1.8.14/harden-runner-bravo_1.8.14_linux_${variant}.tar.gz`,
|
||||
undefined,
|
||||
auth
|
||||
);
|
||||
@@ -131,7 +131,7 @@ export async function installMacosAgent(configStr: string): Promise<boolean> {
|
||||
// Create working directory
|
||||
core.info("Creating /opt/step-security directory...");
|
||||
cp.execSync("sudo mkdir -p /opt/step-security");
|
||||
chownForFolder(process.env.USER, "/opt/step-security");
|
||||
chownForFolder(getRunnerUser(), "/opt/step-security");
|
||||
core.info("✓ Successfully created /opt/step-security directory");
|
||||
|
||||
// Create agent configuration file
|
||||
|
||||
+4
-4
@@ -37,7 +37,7 @@ import {
|
||||
installWindowsAgent,
|
||||
} from "./install-agent";
|
||||
|
||||
import { chownForFolder, detectThirdPartyRunnerProvider, isAgentInstalled, isPlatformSupported, shouldDeployAgentOnSelfHosted } from "./utils";
|
||||
import { chownForFolder, getRunnerUser, detectThirdPartyRunnerProvider, isAgentInstalled, isPlatformSupported, shouldDeployAgentOnSelfHosted } from "./utils";
|
||||
import { buildBravoConfig } from "./bravo-config";
|
||||
|
||||
interface MonitorResponse {
|
||||
@@ -455,7 +455,7 @@ process.on("unhandledRejection", (reason) => {
|
||||
logFile = "/home/agent/agent.log";
|
||||
|
||||
cp.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
chownForFolder(getRunnerUser(), "/home/agent");
|
||||
|
||||
let isTLS = await isTLSEnabled(context.repo.owner);
|
||||
agentInstalled = await installAgent(isTLS, configStr);
|
||||
@@ -575,7 +575,7 @@ export async function installAgentForSelfHosted(owner: string, confg: Configurat
|
||||
const selfHostedConfigStr = JSON.stringify(selfHostedConfig);
|
||||
|
||||
cp.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
chownForFolder(getRunnerUser(), "/home/agent");
|
||||
|
||||
const agentInstalled = await installAgent(isTLS, selfHostedConfigStr);
|
||||
|
||||
@@ -619,7 +619,7 @@ export async function installAgentForBravo(owner: string, bravoConfigStr: string
|
||||
}
|
||||
|
||||
cp.execSync("sudo mkdir -p /home/agent");
|
||||
chownForFolder(process.env.USER, "/home/agent");
|
||||
chownForFolder(getRunnerUser(), "/home/agent");
|
||||
|
||||
await installAgentBravo(bravoConfigStr);
|
||||
} catch (error) {
|
||||
|
||||
@@ -99,6 +99,7 @@ describe("detectThirdPartyRunnerProvider", () => {
|
||||
delete process.env.DEPOT_RUNNER;
|
||||
delete process.env.NAMESPACE_GITHUB_RUNTIME;
|
||||
delete process.env.BITRISE_IO;
|
||||
delete process.env.CODEBUILD_RUNNER_TYPE;
|
||||
delete process.env.RUNNER_NAME;
|
||||
});
|
||||
|
||||
@@ -126,6 +127,16 @@ describe("detectThirdPartyRunnerProvider", () => {
|
||||
expect(detectThirdPartyRunnerProvider()).toBe("bitrise");
|
||||
});
|
||||
|
||||
test("returns codebuild when CODEBUILD_RUNNER_TYPE=GITHUB", () => {
|
||||
process.env.CODEBUILD_RUNNER_TYPE = "GITHUB";
|
||||
expect(detectThirdPartyRunnerProvider()).toBe("codebuild");
|
||||
});
|
||||
|
||||
test("returns null when CODEBUILD_RUNNER_TYPE has a non-GITHUB value", () => {
|
||||
process.env.CODEBUILD_RUNNER_TYPE = "OTHER";
|
||||
expect(detectThirdPartyRunnerProvider()).toBeNull();
|
||||
});
|
||||
|
||||
test("returns warp for RUNNER_NAME prefix warp-", () => {
|
||||
process.env.RUNNER_NAME = "warp-4x-x64-abc";
|
||||
expect(detectThirdPartyRunnerProvider()).toBe("warp");
|
||||
|
||||
+22
-2
@@ -1,5 +1,6 @@
|
||||
import * as cp from "child_process";
|
||||
import * as fs from "fs";
|
||||
import * as os from "os";
|
||||
|
||||
export function isPlatformSupported(platform: NodeJS.Platform) {
|
||||
switch (platform) {
|
||||
@@ -13,7 +14,25 @@ export function isPlatformSupported(platform: NodeJS.Platform) {
|
||||
}
|
||||
}
|
||||
|
||||
export function chownForFolder(newOwner: string, target: string) {
|
||||
// Resolves the user the runner process is executing as. Some runner
|
||||
// environments (e.g. AWS CodeBuild-hosted runners) do not set the USER
|
||||
// environment variable.
|
||||
export function getRunnerUser(): string | undefined {
|
||||
if (process.env.USER) {
|
||||
return process.env.USER;
|
||||
}
|
||||
try {
|
||||
return os.userInfo().username;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function chownForFolder(newOwner: string | undefined, target: string) {
|
||||
if (!newOwner) {
|
||||
console.log(`Unable to determine runner user; skipping chown of ${target}`);
|
||||
return;
|
||||
}
|
||||
let cmd = "sudo";
|
||||
let args = ["chown", "-R", newOwner, target];
|
||||
cp.execFileSync(cmd, args);
|
||||
@@ -40,12 +59,13 @@ export function shouldDeployAgentOnSelfHosted(
|
||||
return deployOnSelfHostedVm && !isContainer && !agentAlreadyInstalled;
|
||||
}
|
||||
|
||||
export type ThirdPartyRunnerProvider = "depot" | "namespace" | "warp" | "blacksmith" | "bitrise";
|
||||
export type ThirdPartyRunnerProvider = "depot" | "namespace" | "warp" | "blacksmith" | "bitrise" | "codebuild";
|
||||
|
||||
export function detectThirdPartyRunnerProvider(): ThirdPartyRunnerProvider | null {
|
||||
if (process.env["DEPOT_RUNNER"] === "1") return "depot";
|
||||
if (process.env["NAMESPACE_GITHUB_RUNTIME"]) return "namespace";
|
||||
if (process.env["BITRISE_IO"]) return "bitrise";
|
||||
if (process.env["CODEBUILD_RUNNER_TYPE"] === "GITHUB") return "codebuild";
|
||||
const runnerName = process.env["RUNNER_NAME"] ?? "";
|
||||
if (runnerName.startsWith("warp-")) return "warp";
|
||||
if (runnerName.startsWith("blacksmith-")) return "blacksmith";
|
||||
|
||||
Reference in New Issue
Block a user