1
0
Fork 0
mirror of synced 2026-06-05 14:28:19 +00:00

Merge pull request #125 from step-security/rel-v1.4.2

Release v1.4.2
This commit is contained in:
Varun Sharma 2022-04-22 09:11:40 -07:00 committed by GitHub
commit 866e511e6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 445 additions and 304 deletions

View file

@ -2,8 +2,8 @@
Harden-Runner GitHub Action installs a security agent on the GitHub-hosted runner (Ubuntu VM) to
1. Monitor the build process,
2. Prevent exfiltration of credentials, and
1. Monitor the build process
2. Prevent exfiltration of credentials
3. Detect compromised dependencies or build tools
<p align="left">
@ -12,11 +12,11 @@ Harden-Runner GitHub Action installs a security agent on the GitHub-hosted runne
## Why
Hijacked dependencies and compromised build tools typically make outbound requests during the build process to exfiltrate data or credentials. There is also a risk that a compromised dependency or build tool may modify source code, dependencies, or artifacts.
Hijacked dependencies and compromised build tools typically make outbound requests to exfiltrate data or credentials, or may modify source code, dependencies, or artifacts during the build.
Harden-Runner automatically correlates outbound traffic, file modifications, and process activity with each step of a workflow. You can also set a policy to restrict outbound traffic.
Check out the [hands-on tutorials](https://github.com/step-security/supply-chain-goat) to learn how `harden-runner` would have prevented past software supply chain attacks.
Check out the [hands-on tutorials](https://github.com/step-security/supply-chain-goat) to learn how Harden-Runner would have prevented past supply chain attacks and read this [blog post](https://infosecwriteups.com/detecting-malware-packages-in-github-actions-7b93a9985635) on how Harden-Runner detected malicious packages.
## How
@ -63,6 +63,12 @@ If you have questions or ideas, please use [discussions](https://github.com/step
4. [Cryptographically verify tools run as part of the CI/ CD pipeline](https://github.com/step-security/harden-runner/discussions/94)
5. [Automatic signing](https://github.com/step-security/harden-runner/discussions/77)
## Limitations
1. Harden-Runner GitHub Action only works for GitHub-hosted runners. Self-hosted runners are not supported.
2. 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).
3. 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.
## Testimonials
> _I think this is a great idea and for the threat model of build-time, an immediate network egress request monitoring makes a lot of sense_ - [Liran Tal](https://stars.github.com/profiles/lirantal/), GitHub Star, and Author of Essential Node.js Security

42
dist/index.js vendored
View file

@ -1696,9 +1696,44 @@ function printInfo(web_url) {
console.log("\x1b[32m%s\x1b[0m", "View security insights and recommended policy at:");
console.log(`${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`);
}
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.";
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.";
// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js
var core = __nccwpck_require__(186);
;// CONCATENATED MODULE: external "node:fs"
const external_node_fs_namespaceObject = require("node:fs");
;// CONCATENATED MODULE: ./node_modules/is-docker/index.js
let isDockerCached;
function hasDockerEnv() {
try {
external_node_fs_namespaceObject.statSync('/.dockerenv');
return true;
} catch {
return false;
}
}
function hasDockerCGroup() {
try {
return external_node_fs_namespaceObject.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
} catch {
return false;
}
}
function isDocker() {
// TODO: Use `??=` when targeting Node.js 16.
if (isDockerCached === undefined) {
isDockerCached = hasDockerEnv() || hasDockerCGroup();
}
return isDockerCached;
}
;// CONCATENATED MODULE: ./src/index.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@ -1711,9 +1746,14 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
};
(() => __awaiter(void 0, void 0, void 0, function* () {
if (process.platform !== "linux") {
console.log("Only runs on linux");
console.log(UBUNTU_MESSAGE);
return;
}
if (isDocker()) {
console.log(CONTAINER_MESSAGE);
return;
}
if (core.getBooleanInput("disable-telemetry") &&

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

49
dist/post/index.js vendored
View file

@ -1697,6 +1697,47 @@ var external_fs_ = __nccwpck_require__(747);
const external_child_process_namespaceObject = require("child_process");
// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js
var core = __nccwpck_require__(186);
;// CONCATENATED MODULE: ./src/common.ts
function printInfo(web_url) {
console.log("\x1b[32m%s\x1b[0m", "View security insights and recommended policy at:");
console.log(`${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`);
}
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.";
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.";
;// CONCATENATED MODULE: external "node:fs"
const external_node_fs_namespaceObject = require("node:fs");
;// CONCATENATED MODULE: ./node_modules/is-docker/index.js
let isDockerCached;
function hasDockerEnv() {
try {
external_node_fs_namespaceObject.statSync('/.dockerenv');
return true;
} catch {
return false;
}
}
function hasDockerCGroup() {
try {
return external_node_fs_namespaceObject.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
} catch {
return false;
}
}
function isDocker() {
// TODO: Use `??=` when targeting Node.js 16.
if (isDockerCached === undefined) {
isDockerCached = hasDockerEnv() || hasDockerCGroup();
}
return isDockerCached;
}
;// CONCATENATED MODULE: ./src/cleanup.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@ -1710,9 +1751,15 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
(() => __awaiter(void 0, void 0, void 0, function* () {
if (process.platform !== "linux") {
console.log("Only runs on linux");
console.log(UBUNTU_MESSAGE);
return;
}
if (isDocker()) {
console.log(CONTAINER_MESSAGE);
return;
}
external_fs_.writeFileSync("/home/agent/post_event.json", JSON.stringify({ event: "post" }));

File diff suppressed because one or more lines are too long

46
dist/pre/index.js vendored
View file

@ -6258,6 +6258,8 @@ function printInfo(web_url) {
console.log("\x1b[32m%s\x1b[0m", "View security insights and recommended policy at:");
console.log(`${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`);
}
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.";
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.";
// EXTERNAL MODULE: ./node_modules/@actions/tool-cache/lib/tool-cache.js
var tool_cache = __nccwpck_require__(7784);
@ -6272,13 +6274,46 @@ function verifyChecksum(downloadPath) {
const checksum = external_crypto_.createHash("sha256")
.update(fileBuffer)
.digest("hex"); // checksum of downloaded file
const expectedChecksum = "8a8d304cb1e413f0fd2c1dffacefc0d91ba693eee2040f4ea7893ef29f3f10b1"; // checksum for v0.9.1
const expectedChecksum = "c9fa91c602954155391c9da6318560d7fb5998155660e4948175c9ab8690716c"; // checksum for v0.9.3
if (checksum !== expectedChecksum) {
core.setFailed(`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`);
}
core.debug("Checksum verification passed.");
}
;// CONCATENATED MODULE: external "node:fs"
const external_node_fs_namespaceObject = require("node:fs");
;// CONCATENATED MODULE: ./node_modules/is-docker/index.js
let isDockerCached;
function hasDockerEnv() {
try {
external_node_fs_namespaceObject.statSync('/.dockerenv');
return true;
} catch {
return false;
}
}
function hasDockerCGroup() {
try {
return external_node_fs_namespaceObject.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
} catch {
return false;
}
}
function isDocker() {
// TODO: Use `??=` when targeting Node.js 16.
if (isDockerCached === undefined) {
isDockerCached = hasDockerEnv() || hasDockerCGroup();
}
return isDockerCached;
}
;// CONCATENATED MODULE: ./src/setup.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@ -6298,10 +6333,15 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
(() => __awaiter(void 0, void 0, void 0, function* () {
try {
if (process.platform !== "linux") {
console.log("Only runs on linux");
console.log(UBUNTU_MESSAGE);
return;
}
if (isDocker()) {
console.log(CONTAINER_MESSAGE);
return;
}
var correlation_id = v4();
@ -6343,7 +6383,7 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
// Note: to avoid github rate limiting
let token = core.getInput("token");
let auth = `token ${token}`;
const downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.9.1/agent_0.9.1_linux_amd64.tar.gz", undefined, auth);
const downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.9.3/agent_0.9.3_linux_amd64.tar.gz", undefined, auth);
verifyChecksum(downloadPath); // NOTE: verifying agent's checksum, before extracting
const extractPath = yield tool_cache.extractTar(downloadPath);
console.log(`Step Security Job Correlation ID: ${correlation_id}`);

File diff suppressed because one or more lines are too long

546
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{
"name": "step-security-harden-runner",
"version": "1.4.0",
"description": "Security monitoring for the GitHub-hosted runner",
"version": "1.4.2",
"description": "Security agent for GitHub-hosted runner to monitor the build process",
"main": "index.js",
"scripts": {
"build": "npm run main && npm run pre && npm run post",
@ -28,6 +28,7 @@
"@actions/http-client": "^1.0.11",
"@actions/tool-cache": "^1.7.1",
"ansi-regex": ">=5.0.1",
"is-docker": "^3.0.0",
"node-fetch": ">=3.2.0",
"uuid": "^8.3.2"
},

View file

@ -10,7 +10,7 @@ export function verifyChecksum(downloadPath: string) {
.digest("hex"); // checksum of downloaded file
const expectedChecksum: string =
"8a8d304cb1e413f0fd2c1dffacefc0d91ba693eee2040f4ea7893ef29f3f10b1"; // checksum for v0.9.1
"c9fa91c602954155391c9da6318560d7fb5998155660e4948175c9ab8690716c"; // checksum for v0.9.3
if (checksum !== expectedChecksum) {
core.setFailed(

View file

@ -1,10 +1,16 @@
import * as fs from "fs";
import * as cp from "child_process";
import * as core from "@actions/core";
import * as common from "./common";
import isDocker from "is-docker";
(async () => {
if (process.platform !== "linux") {
console.log("Only runs on linux");
console.log(common.UBUNTU_MESSAGE);
return;
}
if (isDocker()) {
console.log(common.CONTAINER_MESSAGE);
return;
}

View file

@ -8,3 +8,9 @@ export function printInfo(web_url) {
`${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`
);
}
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.";
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.";

View file

@ -1,9 +1,14 @@
import { printInfo } from "./common";
import * as common from "./common";
import * as core from "@actions/core";
import isDocker from "is-docker";
(async () => {
if (process.platform !== "linux") {
console.log("Only runs on linux");
console.log(common.UBUNTU_MESSAGE);
return;
}
if (isDocker()) {
console.log(common.CONTAINER_MESSAGE);
return;
}
@ -16,6 +21,6 @@ import * as core from "@actions/core";
);
} else {
var web_url = "https://app.stepsecurity.io";
printInfo(web_url);
common.printInfo(web_url);
}
})();

View file

@ -4,13 +4,19 @@ import * as fs from "fs";
import * as httpm from "@actions/http-client";
import * as path from "path";
import { v4 as uuidv4 } from "uuid";
import { printInfo } from "./common";
import * as common from "./common";
import * as tc from "@actions/tool-cache";
import { verifyChecksum } from "./checksum";
import isDocker from "is-docker";
(async () => {
try {
if (process.platform !== "linux") {
console.log("Only runs on linux");
console.log(common.UBUNTU_MESSAGE);
return;
}
if (isDocker()) {
console.log(common.CONTAINER_MESSAGE);
return;
}
@ -65,7 +71,7 @@ import { verifyChecksum } from "./checksum";
let auth = `token ${token}`;
const downloadPath: string = await tc.downloadTool(
"https://github.com/step-security/agent/releases/download/v0.9.1/agent_0.9.1_linux_amd64.tar.gz",
"https://github.com/step-security/agent/releases/download/v0.9.3/agent_0.9.3_linux_amd64.tar.gz",
undefined,
auth
);
@ -76,7 +82,7 @@ import { verifyChecksum } from "./checksum";
console.log(`Step Security Job Correlation ID: ${correlation_id}`);
if (!confg.disable_telemetry || confg.egress_policy === "audit") {
printInfo(web_url);
common.printInfo(web_url);
}
let cmd = "cp",