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

Release v2.3.1 (#281)

This commit is contained in:
Varun Sharma 2023-04-19 13:06:04 -07:00 committed by GitHub
commit 6b3083af28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 340 additions and 167 deletions

View file

@ -1,7 +1,7 @@
<p align="center"> <p align="center">
<picture> <picture>
<source media="(prefers-color-scheme: light)" srcset="images/banner.png" width="400"> <source media="(prefers-color-scheme: light)" srcset="images/banner.png" width="400">
<img src="images/banner.png" width="400"> <img alt="Dark Banner" src="images/banner-dark.png" width="400">
</picture> </picture>
</p> </p>
@ -57,7 +57,7 @@ Read this [case study](https://infosecwriteups.com/detecting-malware-packages-in
<img src="images/buildlog1.png" alt="Link in build log" > <img src="images/buildlog1.png" alt="Link in build log" >
</p> </p>
3. Click on the link ([example link](https://app.stepsecurity.io/github/ossf/scorecard/actions/runs/2265028928)). You will see a process monitor view of file and network activities correlated with each step of the job. 3. Click on the link ([example link](https://app.stepsecurity.io/github/ossf/scorecard/actions/runs/2265028928)). You will see a process monitor view of file and network activities correlated with each step of the job. These insights hold significant value for forensic investigations, proving crucial in the event of an incident.
<p align="left"> <p align="left">
<img src="images/insights2.png" alt="Insights from harden-runner" > <img src="images/insights2.png" alt="Insights from harden-runner" >

5
dist/index.js vendored
View file

@ -2856,7 +2856,10 @@ function addSummary() {
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`; const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
yield core.summary yield core.summary
.addSeparator() .addSeparator()
.addImage("https://github.com/step-security/harden-runner/raw/main/images/banner.png", "StepSecurity Harden-Runner", { width: "200" }) .addRaw(`<p><picture>
<source media="(prefers-color-scheme: light)" srcset="https://github.com/step-security/harden-runner/raw/main/images/banner.png" width="200">
<img alt="Dark Banner" src="https://github.com/step-security/harden-runner/raw/main/images/banner-dark.png" width="200">
</picture></p>`, true)
.addLink("View security insights and recommended policy", insights_url) .addLink("View security insights and recommended policy", insights_url)
.addSeparator() .addSeparator()
.write(); .write();

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

368
dist/post/index.js vendored
View file

@ -82,9 +82,10 @@ exports.isFeatureAvailable = isFeatureAvailable;
* @param primaryKey an explicit key for restoring the cache * @param primaryKey an explicit key for restoring the cache
* @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for key * @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for key
* @param downloadOptions cache download options * @param downloadOptions cache download options
* @param enableCrossOsArchive an optional boolean enabled to restore on windows any cache created on any platform
* @returns string returns the key for the cache hit, otherwise returns undefined * @returns string returns the key for the cache hit, otherwise returns undefined
*/ */
function restoreCache(paths, primaryKey, restoreKeys, options) { function restoreCache(paths, primaryKey, restoreKeys, options, enableCrossOsArchive = false) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
checkPaths(paths); checkPaths(paths);
restoreKeys = restoreKeys || []; restoreKeys = restoreKeys || [];
@ -102,7 +103,8 @@ function restoreCache(paths, primaryKey, restoreKeys, options) {
try { try {
// path are needed to compute version // path are needed to compute version
const cacheEntry = yield cacheHttpClient.getCacheEntry(keys, paths, { const cacheEntry = yield cacheHttpClient.getCacheEntry(keys, paths, {
compressionMethod compressionMethod,
enableCrossOsArchive
}); });
if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.archiveLocation)) { if (!(cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.archiveLocation)) {
// Cache not found // Cache not found
@ -149,10 +151,11 @@ exports.restoreCache = restoreCache;
* *
* @param paths a list of file paths to be cached * @param paths a list of file paths to be cached
* @param key an explicit key for restoring the cache * @param key an explicit key for restoring the cache
* @param enableCrossOsArchive an optional boolean enabled to save cache on windows which could be restored on any platform
* @param options cache upload options * @param options cache upload options
* @returns number returns cacheId if the cache was saved successfully and throws an error if save fails * @returns number returns cacheId if the cache was saved successfully and throws an error if save fails
*/ */
function saveCache(paths, key, options) { function saveCache(paths, key, options, enableCrossOsArchive = false) {
var _a, _b, _c, _d, _e; var _a, _b, _c, _d, _e;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
checkPaths(paths); checkPaths(paths);
@ -183,6 +186,7 @@ function saveCache(paths, key, options) {
core.debug('Reserving Cache'); core.debug('Reserving Cache');
const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, { const reserveCacheResponse = yield cacheHttpClient.reserveCache(key, paths, {
compressionMethod, compressionMethod,
enableCrossOsArchive,
cacheSize: archiveFileSize cacheSize: archiveFileSize
}); });
if ((_a = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.result) === null || _a === void 0 ? void 0 : _a.cacheId) { if ((_a = reserveCacheResponse === null || reserveCacheResponse === void 0 ? void 0 : reserveCacheResponse.result) === null || _a === void 0 ? void 0 : _a.cacheId) {
@ -255,7 +259,6 @@ const crypto = __importStar(__nccwpck_require__(6417));
const fs = __importStar(__nccwpck_require__(5747)); const fs = __importStar(__nccwpck_require__(5747));
const url_1 = __nccwpck_require__(8835); const url_1 = __nccwpck_require__(8835);
const utils = __importStar(__nccwpck_require__(1518)); const utils = __importStar(__nccwpck_require__(1518));
const constants_1 = __nccwpck_require__(8840);
const downloadUtils_1 = __nccwpck_require__(5500); const downloadUtils_1 = __nccwpck_require__(5500);
const options_1 = __nccwpck_require__(6215); const options_1 = __nccwpck_require__(6215);
const requestUtils_1 = __nccwpck_require__(3981); const requestUtils_1 = __nccwpck_require__(3981);
@ -285,10 +288,17 @@ function createHttpClient() {
const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token); const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token);
return new http_client_1.HttpClient('actions/cache', [bearerCredentialHandler], getRequestOptions()); return new http_client_1.HttpClient('actions/cache', [bearerCredentialHandler], getRequestOptions());
} }
function getCacheVersion(paths, compressionMethod) { function getCacheVersion(paths, compressionMethod, enableCrossOsArchive = false) {
const components = paths.concat(!compressionMethod || compressionMethod === constants_1.CompressionMethod.Gzip const components = paths;
? [] // Add compression method to cache version to restore
: [compressionMethod]); // compressed cache as per compression method
if (compressionMethod) {
components.push(compressionMethod);
}
// Only check for windows platforms if enableCrossOsArchive is false
if (process.platform === 'win32' && !enableCrossOsArchive) {
components.push('windows-only');
}
// Add salt to cache version to support breaking changes in cache entry // Add salt to cache version to support breaking changes in cache entry
components.push(versionSalt); components.push(versionSalt);
return crypto return crypto
@ -300,10 +310,15 @@ exports.getCacheVersion = getCacheVersion;
function getCacheEntry(keys, paths, options) { function getCacheEntry(keys, paths, options) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const httpClient = createHttpClient(); const httpClient = createHttpClient();
const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod); const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive);
const resource = `cache?keys=${encodeURIComponent(keys.join(','))}&version=${version}`; const resource = `cache?keys=${encodeURIComponent(keys.join(','))}&version=${version}`;
const response = yield requestUtils_1.retryTypedResponse('getCacheEntry', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); })); const response = yield requestUtils_1.retryTypedResponse('getCacheEntry', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); }));
// Cache not found
if (response.statusCode === 204) { if (response.statusCode === 204) {
// List cache for primary key only if cache miss occurs
if (core.isDebug()) {
yield printCachesListForDiagnostics(keys[0], httpClient, version);
}
return null; return null;
} }
if (!requestUtils_1.isSuccessStatusCode(response.statusCode)) { if (!requestUtils_1.isSuccessStatusCode(response.statusCode)) {
@ -312,6 +327,7 @@ function getCacheEntry(keys, paths, options) {
const cacheResult = response.result; const cacheResult = response.result;
const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation; const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation;
if (!cacheDownloadUrl) { if (!cacheDownloadUrl) {
// Cache achiveLocation not found. This should never happen, and hence bail out.
throw new Error('Cache not found.'); throw new Error('Cache not found.');
} }
core.setSecret(cacheDownloadUrl); core.setSecret(cacheDownloadUrl);
@ -321,6 +337,22 @@ function getCacheEntry(keys, paths, options) {
}); });
} }
exports.getCacheEntry = getCacheEntry; exports.getCacheEntry = getCacheEntry;
function printCachesListForDiagnostics(key, httpClient, version) {
return __awaiter(this, void 0, void 0, function* () {
const resource = `caches?key=${encodeURIComponent(key)}`;
const response = yield requestUtils_1.retryTypedResponse('listCache', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); }));
if (response.statusCode === 200) {
const cacheListResult = response.result;
const totalCount = cacheListResult === null || cacheListResult === void 0 ? void 0 : cacheListResult.totalCount;
if (totalCount && totalCount > 0) {
core.debug(`No matching cache found for cache key '${key}', version '${version} and scope ${process.env['GITHUB_REF']}. There exist one or more cache(s) with similar key but they have different version or scope. See more info on cache matching here: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key \nOther caches with similar key:`);
for (const cacheEntry of (cacheListResult === null || cacheListResult === void 0 ? void 0 : cacheListResult.artifactCaches) || []) {
core.debug(`Cache Key: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheKey}, Cache Version: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheVersion}, Cache Scope: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.scope}, Cache Created: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.creationTime}`);
}
}
}
});
}
function downloadCache(archiveLocation, archivePath, options) { function downloadCache(archiveLocation, archivePath, options) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const archiveUrl = new url_1.URL(archiveLocation); const archiveUrl = new url_1.URL(archiveLocation);
@ -341,7 +373,7 @@ exports.downloadCache = downloadCache;
function reserveCache(key, paths, options) { function reserveCache(key, paths, options) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const httpClient = createHttpClient(); const httpClient = createHttpClient();
const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod); const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive);
const reserveCacheRequest = { const reserveCacheRequest = {
key, key,
version, version,
@ -559,12 +591,13 @@ function unlinkFile(filePath) {
}); });
} }
exports.unlinkFile = unlinkFile; exports.unlinkFile = unlinkFile;
function getVersion(app) { function getVersion(app, additionalArgs = []) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
core.debug(`Checking ${app} --version`);
let versionOutput = ''; let versionOutput = '';
additionalArgs.push('--version');
core.debug(`Checking ${app} ${additionalArgs.join(' ')}`);
try { try {
yield exec.exec(`${app} --version`, [], { yield exec.exec(`${app}`, additionalArgs, {
ignoreReturnCode: true, ignoreReturnCode: true,
silent: true, silent: true,
listeners: { listeners: {
@ -584,23 +617,14 @@ function getVersion(app) {
// Use zstandard if possible to maximize cache performance // Use zstandard if possible to maximize cache performance
function getCompressionMethod() { function getCompressionMethod() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (process.platform === 'win32' && !(yield isGnuTarInstalled())) { const versionOutput = yield getVersion('zstd', ['--quiet']);
// Disable zstd due to bug https://github.com/actions/cache/issues/301
return constants_1.CompressionMethod.Gzip;
}
const versionOutput = yield getVersion('zstd');
const version = semver.clean(versionOutput); const version = semver.clean(versionOutput);
if (!versionOutput.toLowerCase().includes('zstd command line interface')) { core.debug(`zstd version: ${version}`);
// zstd is not installed if (versionOutput === '') {
return constants_1.CompressionMethod.Gzip; return constants_1.CompressionMethod.Gzip;
} }
else if (!version || semver.lt(version, 'v1.3.2')) {
// zstd is installed but using a version earlier than v1.3.2
// v1.3.2 is required to use the `--long` options in zstd
return constants_1.CompressionMethod.ZstdWithoutLong;
}
else { else {
return constants_1.CompressionMethod.Zstd; return constants_1.CompressionMethod.ZstdWithoutLong;
} }
}); });
} }
@ -611,13 +635,16 @@ function getCacheFileName(compressionMethod) {
: constants_1.CacheFilename.Zstd; : constants_1.CacheFilename.Zstd;
} }
exports.getCacheFileName = getCacheFileName; exports.getCacheFileName = getCacheFileName;
function isGnuTarInstalled() { function getGnuTarPathOnWindows() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (fs.existsSync(constants_1.GnuTarPathOnWindows)) {
return constants_1.GnuTarPathOnWindows;
}
const versionOutput = yield getVersion('tar'); const versionOutput = yield getVersion('tar');
return versionOutput.toLowerCase().includes('gnu tar'); return versionOutput.toLowerCase().includes('gnu tar') ? io.which('tar') : '';
}); });
} }
exports.isGnuTarInstalled = isGnuTarInstalled; exports.getGnuTarPathOnWindows = getGnuTarPathOnWindows;
function assertDefined(name, value) { function assertDefined(name, value) {
if (value === undefined) { if (value === undefined) {
throw Error(`Expected ${name} but value was undefiend`); throw Error(`Expected ${name} but value was undefiend`);
@ -653,6 +680,11 @@ var CompressionMethod;
CompressionMethod["ZstdWithoutLong"] = "zstd-without-long"; CompressionMethod["ZstdWithoutLong"] = "zstd-without-long";
CompressionMethod["Zstd"] = "zstd"; CompressionMethod["Zstd"] = "zstd";
})(CompressionMethod = exports.CompressionMethod || (exports.CompressionMethod = {})); })(CompressionMethod = exports.CompressionMethod || (exports.CompressionMethod = {}));
var ArchiveToolType;
(function (ArchiveToolType) {
ArchiveToolType["GNU"] = "gnu";
ArchiveToolType["BSD"] = "bsd";
})(ArchiveToolType = exports.ArchiveToolType || (exports.ArchiveToolType = {}));
// The default number of retry attempts. // The default number of retry attempts.
exports.DefaultRetryAttempts = 2; exports.DefaultRetryAttempts = 2;
// The default delay in milliseconds between retry attempts. // The default delay in milliseconds between retry attempts.
@ -661,6 +693,12 @@ exports.DefaultRetryDelay = 5000;
// over the socket during this period, the socket is destroyed and the download // over the socket during this period, the socket is destroyed and the download
// is aborted. // is aborted.
exports.SocketTimeout = 5000; exports.SocketTimeout = 5000;
// The default path of GNUtar on hosted Windows runners
exports.GnuTarPathOnWindows = `${process.env['PROGRAMFILES']}\\Git\\usr\\bin\\tar.exe`;
// The default path of BSDtar on hosted Windows runners
exports.SystemTarPathOnWindows = `${process.env['SYSTEMDRIVE']}\\Windows\\System32\\tar.exe`;
exports.TarFilename = 'cache.tar';
exports.ManifestFilename = 'manifest.txt';
//# sourceMappingURL=constants.js.map //# sourceMappingURL=constants.js.map
/***/ }), /***/ }),
@ -1079,21 +1117,19 @@ const path = __importStar(__nccwpck_require__(5622));
const utils = __importStar(__nccwpck_require__(1518)); const utils = __importStar(__nccwpck_require__(1518));
const constants_1 = __nccwpck_require__(8840); const constants_1 = __nccwpck_require__(8840);
const IS_WINDOWS = process.platform === 'win32'; const IS_WINDOWS = process.platform === 'win32';
function getTarPath(args, compressionMethod) { // Returns tar path and type: BSD or GNU
function getTarPath() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
switch (process.platform) { switch (process.platform) {
case 'win32': { case 'win32': {
const systemTar = `${process.env['windir']}\\System32\\tar.exe`; const gnuTar = yield utils.getGnuTarPathOnWindows();
if (compressionMethod !== constants_1.CompressionMethod.Gzip) { const systemTar = constants_1.SystemTarPathOnWindows;
// We only use zstandard compression on windows when gnu tar is installed due to if (gnuTar) {
// a bug with compressing large files with bsdtar + zstd // Use GNUtar as default on windows
args.push('--force-local'); return { path: gnuTar, type: constants_1.ArchiveToolType.GNU };
} }
else if (fs_1.existsSync(systemTar)) { else if (fs_1.existsSync(systemTar)) {
return systemTar; return { path: systemTar, type: constants_1.ArchiveToolType.BSD };
}
else if (yield utils.isGnuTarInstalled()) {
args.push('--force-local');
} }
break; break;
} }
@ -1101,25 +1137,92 @@ function getTarPath(args, compressionMethod) {
const gnuTar = yield io.which('gtar', false); const gnuTar = yield io.which('gtar', false);
if (gnuTar) { if (gnuTar) {
// fix permission denied errors when extracting BSD tar archive with GNU tar - https://github.com/actions/cache/issues/527 // fix permission denied errors when extracting BSD tar archive with GNU tar - https://github.com/actions/cache/issues/527
args.push('--delay-directory-restore'); return { path: gnuTar, type: constants_1.ArchiveToolType.GNU };
return gnuTar; }
else {
return {
path: yield io.which('tar', true),
type: constants_1.ArchiveToolType.BSD
};
} }
break;
} }
default: default:
break; break;
} }
return yield io.which('tar', true); // Default assumption is GNU tar is present in path
return {
path: yield io.which('tar', true),
type: constants_1.ArchiveToolType.GNU
};
}); });
} }
function execTar(args, compressionMethod, cwd) { // Return arguments for tar as per tarPath, compressionMethod, method type and os
function getTarArgs(tarPath, compressionMethod, type, archivePath = '') {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
try { const args = [`"${tarPath.path}"`];
yield exec_1.exec(`"${yield getTarPath(args, compressionMethod)}"`, args, { cwd }); const cacheFileName = utils.getCacheFileName(compressionMethod);
const tarFile = 'cache.tar';
const workingDirectory = getWorkingDirectory();
// Speficic args for BSD tar on windows for workaround
const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
compressionMethod !== constants_1.CompressionMethod.Gzip &&
IS_WINDOWS;
// Method specific args
switch (type) {
case 'create':
args.push('--posix', '-cf', BSD_TAR_ZSTD
? tarFile
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '--exclude', BSD_TAR_ZSTD
? tarFile
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '--files-from', constants_1.ManifestFilename);
break;
case 'extract':
args.push('-xf', BSD_TAR_ZSTD
? tarFile
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P', '-C', workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'));
break;
case 'list':
args.push('-tf', BSD_TAR_ZSTD
? tarFile
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), '-P');
break;
} }
catch (error) { // Platform specific args
throw new Error(`Tar failed with error: ${error === null || error === void 0 ? void 0 : error.message}`); if (tarPath.type === constants_1.ArchiveToolType.GNU) {
switch (process.platform) {
case 'win32':
args.push('--force-local');
break;
case 'darwin':
args.push('--delay-directory-restore');
break;
}
} }
return args;
});
}
// Returns commands to run tar and compression program
function getCommands(compressionMethod, type, archivePath = '') {
return __awaiter(this, void 0, void 0, function* () {
let args;
const tarPath = yield getTarPath();
const tarArgs = yield getTarArgs(tarPath, compressionMethod, type, archivePath);
const compressionArgs = type !== 'create'
? yield getDecompressionProgram(tarPath, compressionMethod, archivePath)
: yield getCompressionProgram(tarPath, compressionMethod);
const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
compressionMethod !== constants_1.CompressionMethod.Gzip &&
IS_WINDOWS;
if (BSD_TAR_ZSTD && type !== 'create') {
args = [[...compressionArgs].join(' '), [...tarArgs].join(' ')];
}
else {
args = [[...tarArgs].join(' '), [...compressionArgs].join(' ')];
}
if (BSD_TAR_ZSTD) {
return args;
}
return [args.join(' ')];
}); });
} }
function getWorkingDirectory() { function getWorkingDirectory() {
@ -1127,91 +1230,119 @@ function getWorkingDirectory() {
return (_a = process.env['GITHUB_WORKSPACE']) !== null && _a !== void 0 ? _a : process.cwd(); return (_a = process.env['GITHUB_WORKSPACE']) !== null && _a !== void 0 ? _a : process.cwd();
} }
// Common function for extractTar and listTar to get the compression method // Common function for extractTar and listTar to get the compression method
function getCompressionProgram(compressionMethod) { function getDecompressionProgram(tarPath, compressionMethod, archivePath) {
// -d: Decompress. return __awaiter(this, void 0, void 0, function* () {
// unzstd is equivalent to 'zstd -d' // -d: Decompress.
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit. // unzstd is equivalent to 'zstd -d'
// Using 30 here because we also support 32-bit self-hosted runners. // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
switch (compressionMethod) { // Using 30 here because we also support 32-bit self-hosted runners.
case constants_1.CompressionMethod.Zstd: const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
return [ compressionMethod !== constants_1.CompressionMethod.Gzip &&
'--use-compress-program', IS_WINDOWS;
IS_WINDOWS ? 'zstd -d --long=30' : 'unzstd --long=30' switch (compressionMethod) {
]; case constants_1.CompressionMethod.Zstd:
case constants_1.CompressionMethod.ZstdWithoutLong: return BSD_TAR_ZSTD
return ['--use-compress-program', IS_WINDOWS ? 'zstd -d' : 'unzstd']; ? [
default: 'zstd -d --long=30 --force -o',
return ['-z']; constants_1.TarFilename,
} archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
]
: [
'--use-compress-program',
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
];
case constants_1.CompressionMethod.ZstdWithoutLong:
return BSD_TAR_ZSTD
? [
'zstd -d --force -o',
constants_1.TarFilename,
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
]
: ['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'];
default:
return ['-z'];
}
});
} }
// Used for creating the archive
// -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores.
// zstdmt is equivalent to 'zstd -T0'
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
// Using 30 here because we also support 32-bit self-hosted runners.
// Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd.
function getCompressionProgram(tarPath, compressionMethod) {
return __awaiter(this, void 0, void 0, function* () {
const cacheFileName = utils.getCacheFileName(compressionMethod);
const BSD_TAR_ZSTD = tarPath.type === constants_1.ArchiveToolType.BSD &&
compressionMethod !== constants_1.CompressionMethod.Gzip &&
IS_WINDOWS;
switch (compressionMethod) {
case constants_1.CompressionMethod.Zstd:
return BSD_TAR_ZSTD
? [
'zstd -T0 --long=30 --force -o',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
constants_1.TarFilename
]
: [
'--use-compress-program',
IS_WINDOWS ? '"zstd -T0 --long=30"' : 'zstdmt --long=30'
];
case constants_1.CompressionMethod.ZstdWithoutLong:
return BSD_TAR_ZSTD
? [
'zstd -T0 --force -o',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
constants_1.TarFilename
]
: ['--use-compress-program', IS_WINDOWS ? '"zstd -T0"' : 'zstdmt'];
default:
return ['-z'];
}
});
}
// Executes all commands as separate processes
function execCommands(commands, cwd) {
return __awaiter(this, void 0, void 0, function* () {
for (const command of commands) {
try {
yield exec_1.exec(command, undefined, {
cwd,
env: Object.assign(Object.assign({}, process.env), { MSYS: 'winsymlinks:nativestrict' })
});
}
catch (error) {
throw new Error(`${command.split(' ')[0]} failed with error: ${error === null || error === void 0 ? void 0 : error.message}`);
}
}
});
}
// List the contents of a tar
function listTar(archivePath, compressionMethod) { function listTar(archivePath, compressionMethod) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const args = [ const commands = yield getCommands(compressionMethod, 'list', archivePath);
...getCompressionProgram(compressionMethod), yield execCommands(commands);
'-tf',
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'-P'
];
yield execTar(args, compressionMethod);
}); });
} }
exports.listTar = listTar; exports.listTar = listTar;
// Extract a tar
function extractTar(archivePath, compressionMethod) { function extractTar(archivePath, compressionMethod) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
// Create directory to extract tar into // Create directory to extract tar into
const workingDirectory = getWorkingDirectory(); const workingDirectory = getWorkingDirectory();
yield io.mkdirP(workingDirectory); yield io.mkdirP(workingDirectory);
const args = [ const commands = yield getCommands(compressionMethod, 'extract', archivePath);
...getCompressionProgram(compressionMethod), yield execCommands(commands);
'-xf',
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'-P',
'-C',
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
];
yield execTar(args, compressionMethod);
}); });
} }
exports.extractTar = extractTar; exports.extractTar = extractTar;
// Create a tar
function createTar(archiveFolder, sourceDirectories, compressionMethod) { function createTar(archiveFolder, sourceDirectories, compressionMethod) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
// Write source directories to manifest.txt to avoid command length limits // Write source directories to manifest.txt to avoid command length limits
const manifestFilename = 'manifest.txt'; fs_1.writeFileSync(path.join(archiveFolder, constants_1.ManifestFilename), sourceDirectories.join('\n'));
const cacheFileName = utils.getCacheFileName(compressionMethod); const commands = yield getCommands(compressionMethod, 'create');
fs_1.writeFileSync(path.join(archiveFolder, manifestFilename), sourceDirectories.join('\n')); yield execCommands(commands, archiveFolder);
const workingDirectory = getWorkingDirectory();
// -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores.
// zstdmt is equivalent to 'zstd -T0'
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
// Using 30 here because we also support 32-bit self-hosted runners.
// Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd.
function getCompressionProgram() {
switch (compressionMethod) {
case constants_1.CompressionMethod.Zstd:
return [
'--use-compress-program',
IS_WINDOWS ? 'zstd -T0 --long=30' : 'zstdmt --long=30'
];
case constants_1.CompressionMethod.ZstdWithoutLong:
return ['--use-compress-program', IS_WINDOWS ? 'zstd -T0' : 'zstdmt'];
default:
return ['-z'];
}
}
const args = [
'--posix',
...getCompressionProgram(),
'-cf',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'--exclude',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'-P',
'-C',
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'--files-from',
manifestFilename
];
yield execTar(args, compressionMethod, archiveFolder);
}); });
} }
exports.createTar = createTar; exports.createTar = createTar;
@ -61026,7 +61157,10 @@ function addSummary() {
const web_url = "https://app.stepsecurity.io"; const web_url = "https://app.stepsecurity.io";
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`; const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
yield core.summary.addSeparator() yield core.summary.addSeparator()
.addImage("https://github.com/step-security/harden-runner/raw/main/images/banner.png", "StepSecurity Harden-Runner", { width: "200" }) .addRaw(`<p><picture>
<source media="(prefers-color-scheme: light)" srcset="https://github.com/step-security/harden-runner/raw/main/images/banner.png" width="200">
<img alt="Dark Banner" src="https://github.com/step-security/harden-runner/raw/main/images/banner-dark.png" width="200">
</picture></p>`, true)
.addLink("View security insights and recommended policy", insights_url) .addLink("View security insights and recommended policy", insights_url)
.addSeparator() .addSeparator()
.write(); .write();

File diff suppressed because one or more lines are too long

92
dist/pre/index.js vendored
View file

@ -46,7 +46,6 @@ const crypto = __importStar(__nccwpck_require__(6417));
const fs = __importStar(__nccwpck_require__(5747)); const fs = __importStar(__nccwpck_require__(5747));
const url_1 = __nccwpck_require__(8835); const url_1 = __nccwpck_require__(8835);
const utils = __importStar(__nccwpck_require__(1518)); const utils = __importStar(__nccwpck_require__(1518));
const constants_1 = __nccwpck_require__(8840);
const downloadUtils_1 = __nccwpck_require__(5500); const downloadUtils_1 = __nccwpck_require__(5500);
const options_1 = __nccwpck_require__(6215); const options_1 = __nccwpck_require__(6215);
const requestUtils_1 = __nccwpck_require__(3981); const requestUtils_1 = __nccwpck_require__(3981);
@ -76,10 +75,17 @@ function createHttpClient() {
const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token); const bearerCredentialHandler = new auth_1.BearerCredentialHandler(token);
return new http_client_1.HttpClient('actions/cache', [bearerCredentialHandler], getRequestOptions()); return new http_client_1.HttpClient('actions/cache', [bearerCredentialHandler], getRequestOptions());
} }
function getCacheVersion(paths, compressionMethod) { function getCacheVersion(paths, compressionMethod, enableCrossOsArchive = false) {
const components = paths.concat(!compressionMethod || compressionMethod === constants_1.CompressionMethod.Gzip const components = paths;
? [] // Add compression method to cache version to restore
: [compressionMethod]); // compressed cache as per compression method
if (compressionMethod) {
components.push(compressionMethod);
}
// Only check for windows platforms if enableCrossOsArchive is false
if (process.platform === 'win32' && !enableCrossOsArchive) {
components.push('windows-only');
}
// Add salt to cache version to support breaking changes in cache entry // Add salt to cache version to support breaking changes in cache entry
components.push(versionSalt); components.push(versionSalt);
return crypto return crypto
@ -91,10 +97,15 @@ exports.getCacheVersion = getCacheVersion;
function getCacheEntry(keys, paths, options) { function getCacheEntry(keys, paths, options) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const httpClient = createHttpClient(); const httpClient = createHttpClient();
const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod); const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive);
const resource = `cache?keys=${encodeURIComponent(keys.join(','))}&version=${version}`; const resource = `cache?keys=${encodeURIComponent(keys.join(','))}&version=${version}`;
const response = yield requestUtils_1.retryTypedResponse('getCacheEntry', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); })); const response = yield requestUtils_1.retryTypedResponse('getCacheEntry', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); }));
// Cache not found
if (response.statusCode === 204) { if (response.statusCode === 204) {
// List cache for primary key only if cache miss occurs
if (core.isDebug()) {
yield printCachesListForDiagnostics(keys[0], httpClient, version);
}
return null; return null;
} }
if (!requestUtils_1.isSuccessStatusCode(response.statusCode)) { if (!requestUtils_1.isSuccessStatusCode(response.statusCode)) {
@ -103,6 +114,7 @@ function getCacheEntry(keys, paths, options) {
const cacheResult = response.result; const cacheResult = response.result;
const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation; const cacheDownloadUrl = cacheResult === null || cacheResult === void 0 ? void 0 : cacheResult.archiveLocation;
if (!cacheDownloadUrl) { if (!cacheDownloadUrl) {
// Cache achiveLocation not found. This should never happen, and hence bail out.
throw new Error('Cache not found.'); throw new Error('Cache not found.');
} }
core.setSecret(cacheDownloadUrl); core.setSecret(cacheDownloadUrl);
@ -112,6 +124,22 @@ function getCacheEntry(keys, paths, options) {
}); });
} }
exports.getCacheEntry = getCacheEntry; exports.getCacheEntry = getCacheEntry;
function printCachesListForDiagnostics(key, httpClient, version) {
return __awaiter(this, void 0, void 0, function* () {
const resource = `caches?key=${encodeURIComponent(key)}`;
const response = yield requestUtils_1.retryTypedResponse('listCache', () => __awaiter(this, void 0, void 0, function* () { return httpClient.getJson(getCacheApiUrl(resource)); }));
if (response.statusCode === 200) {
const cacheListResult = response.result;
const totalCount = cacheListResult === null || cacheListResult === void 0 ? void 0 : cacheListResult.totalCount;
if (totalCount && totalCount > 0) {
core.debug(`No matching cache found for cache key '${key}', version '${version} and scope ${process.env['GITHUB_REF']}. There exist one or more cache(s) with similar key but they have different version or scope. See more info on cache matching here: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key \nOther caches with similar key:`);
for (const cacheEntry of (cacheListResult === null || cacheListResult === void 0 ? void 0 : cacheListResult.artifactCaches) || []) {
core.debug(`Cache Key: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheKey}, Cache Version: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.cacheVersion}, Cache Scope: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.scope}, Cache Created: ${cacheEntry === null || cacheEntry === void 0 ? void 0 : cacheEntry.creationTime}`);
}
}
}
});
}
function downloadCache(archiveLocation, archivePath, options) { function downloadCache(archiveLocation, archivePath, options) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const archiveUrl = new url_1.URL(archiveLocation); const archiveUrl = new url_1.URL(archiveLocation);
@ -132,7 +160,7 @@ exports.downloadCache = downloadCache;
function reserveCache(key, paths, options) { function reserveCache(key, paths, options) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const httpClient = createHttpClient(); const httpClient = createHttpClient();
const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod); const version = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive);
const reserveCacheRequest = { const reserveCacheRequest = {
key, key,
version, version,
@ -350,12 +378,13 @@ function unlinkFile(filePath) {
}); });
} }
exports.unlinkFile = unlinkFile; exports.unlinkFile = unlinkFile;
function getVersion(app) { function getVersion(app, additionalArgs = []) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
core.debug(`Checking ${app} --version`);
let versionOutput = ''; let versionOutput = '';
additionalArgs.push('--version');
core.debug(`Checking ${app} ${additionalArgs.join(' ')}`);
try { try {
yield exec.exec(`${app} --version`, [], { yield exec.exec(`${app}`, additionalArgs, {
ignoreReturnCode: true, ignoreReturnCode: true,
silent: true, silent: true,
listeners: { listeners: {
@ -375,23 +404,14 @@ function getVersion(app) {
// Use zstandard if possible to maximize cache performance // Use zstandard if possible to maximize cache performance
function getCompressionMethod() { function getCompressionMethod() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (process.platform === 'win32' && !(yield isGnuTarInstalled())) { const versionOutput = yield getVersion('zstd', ['--quiet']);
// Disable zstd due to bug https://github.com/actions/cache/issues/301
return constants_1.CompressionMethod.Gzip;
}
const versionOutput = yield getVersion('zstd');
const version = semver.clean(versionOutput); const version = semver.clean(versionOutput);
if (!versionOutput.toLowerCase().includes('zstd command line interface')) { core.debug(`zstd version: ${version}`);
// zstd is not installed if (versionOutput === '') {
return constants_1.CompressionMethod.Gzip; return constants_1.CompressionMethod.Gzip;
} }
else if (!version || semver.lt(version, 'v1.3.2')) {
// zstd is installed but using a version earlier than v1.3.2
// v1.3.2 is required to use the `--long` options in zstd
return constants_1.CompressionMethod.ZstdWithoutLong;
}
else { else {
return constants_1.CompressionMethod.Zstd; return constants_1.CompressionMethod.ZstdWithoutLong;
} }
}); });
} }
@ -402,13 +422,16 @@ function getCacheFileName(compressionMethod) {
: constants_1.CacheFilename.Zstd; : constants_1.CacheFilename.Zstd;
} }
exports.getCacheFileName = getCacheFileName; exports.getCacheFileName = getCacheFileName;
function isGnuTarInstalled() { function getGnuTarPathOnWindows() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (fs.existsSync(constants_1.GnuTarPathOnWindows)) {
return constants_1.GnuTarPathOnWindows;
}
const versionOutput = yield getVersion('tar'); const versionOutput = yield getVersion('tar');
return versionOutput.toLowerCase().includes('gnu tar'); return versionOutput.toLowerCase().includes('gnu tar') ? io.which('tar') : '';
}); });
} }
exports.isGnuTarInstalled = isGnuTarInstalled; exports.getGnuTarPathOnWindows = getGnuTarPathOnWindows;
function assertDefined(name, value) { function assertDefined(name, value) {
if (value === undefined) { if (value === undefined) {
throw Error(`Expected ${name} but value was undefiend`); throw Error(`Expected ${name} but value was undefiend`);
@ -444,6 +467,11 @@ var CompressionMethod;
CompressionMethod["ZstdWithoutLong"] = "zstd-without-long"; CompressionMethod["ZstdWithoutLong"] = "zstd-without-long";
CompressionMethod["Zstd"] = "zstd"; CompressionMethod["Zstd"] = "zstd";
})(CompressionMethod = exports.CompressionMethod || (exports.CompressionMethod = {})); })(CompressionMethod = exports.CompressionMethod || (exports.CompressionMethod = {}));
var ArchiveToolType;
(function (ArchiveToolType) {
ArchiveToolType["GNU"] = "gnu";
ArchiveToolType["BSD"] = "bsd";
})(ArchiveToolType = exports.ArchiveToolType || (exports.ArchiveToolType = {}));
// The default number of retry attempts. // The default number of retry attempts.
exports.DefaultRetryAttempts = 2; exports.DefaultRetryAttempts = 2;
// The default delay in milliseconds between retry attempts. // The default delay in milliseconds between retry attempts.
@ -452,6 +480,12 @@ exports.DefaultRetryDelay = 5000;
// over the socket during this period, the socket is destroyed and the download // over the socket during this period, the socket is destroyed and the download
// is aborted. // is aborted.
exports.SocketTimeout = 5000; exports.SocketTimeout = 5000;
// The default path of GNUtar on hosted Windows runners
exports.GnuTarPathOnWindows = `${process.env['PROGRAMFILES']}\\Git\\usr\\bin\\tar.exe`;
// The default path of BSDtar on hosted Windows runners
exports.SystemTarPathOnWindows = `${process.env['SYSTEMDRIVE']}\\Windows\\System32\\tar.exe`;
exports.TarFilename = 'cache.tar';
exports.ManifestFilename = 'manifest.txt';
//# sourceMappingURL=constants.js.map //# sourceMappingURL=constants.js.map
/***/ }), /***/ }),
@ -68974,7 +69008,10 @@ function addSummary() {
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`; const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
yield core.summary yield core.summary
.addSeparator() .addSeparator()
.addImage("https://github.com/step-security/harden-runner/raw/main/images/banner.png", "StepSecurity Harden-Runner", { width: "200" }) .addRaw(`<p><picture>
<source media="(prefers-color-scheme: light)" srcset="https://github.com/step-security/harden-runner/raw/main/images/banner.png" width="200">
<img alt="Dark Banner" src="https://github.com/step-security/harden-runner/raw/main/images/banner-dark.png" width="200">
</picture></p>`, true)
.addLink("View security insights and recommended policy", insights_url) .addLink("View security insights and recommended policy", insights_url)
.addSeparator() .addSeparator()
.write(); .write();
@ -69181,7 +69218,6 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
disable_telemetry: lib_core.getBooleanInput("disable-telemetry"), disable_telemetry: lib_core.getBooleanInput("disable-telemetry"),
disable_sudo: lib_core.getBooleanInput("disable-sudo"), disable_sudo: lib_core.getBooleanInput("disable-sudo"),
disable_file_monitoring: lib_core.getBooleanInput("disable-file-monitoring"), disable_file_monitoring: lib_core.getBooleanInput("disable-file-monitoring"),
private: github.context.payload.repository.private,
}; };
let policyName = lib_core.getInput("policy"); let policyName = lib_core.getInput("policy");
if (policyName !== "") { if (policyName !== "") {

File diff suppressed because one or more lines are too long

BIN
images/banner-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "step-security-harden-runner", "name": "step-security-harden-runner",
"version": "2.2.0", "version": "2.3.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "step-security-harden-runner", "name": "step-security-harden-runner",
"version": "2.2.0", "version": "2.3.0",
"license": "Apache License 2.0", "license": "Apache License 2.0",
"dependencies": { "dependencies": {
"@actions/cache": "^3.1.4", "@actions/cache": "^3.1.4",

View file

@ -1,6 +1,6 @@
{ {
"name": "step-security-harden-runner", "name": "step-security-harden-runner",
"version": "2.3.0", "version": "2.3.1",
"description": "Security agent for GitHub-hosted runner to monitor the build process", "description": "Security agent for GitHub-hosted runner to monitor the build process",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View file

@ -3,8 +3,11 @@ import * as cp from "child_process";
test("adding stepsecurity summary in github_summary", async () => { test("adding stepsecurity summary in github_summary", async () => {
let expected = `<hr> let expected = `<hr>
<img src="https://github.com/step-security/harden-runner/raw/main/images/banner.png" alt="StepSecurity Harden-Runner" width="200"> <p><picture>
<a href="https://app.stepsecurity.io/github/step-security/test/actions/runs/12345">View security insights and recommended policy</a> <source media=\"(prefers-color-scheme: light)\" srcset=\"https://github.com/step-security/harden-runner/raw/main/images/banner.png\" width=\"200\">
<img alt=\"Dark Banner\" src=\"https://github.com/step-security/harden-runner/raw/main/images/banner-dark.png\" width=\"200\">
</picture></p>
<a href=\"https://app.stepsecurity.io/github/step-security/test/actions/runs/12345\">View security insights and recommended policy</a>
<hr> <hr>
`; `;
@ -22,5 +25,4 @@ test("adding stepsecurity summary in github_summary", async () => {
cp.execSync(`rm ${github_summary}`); cp.execSync(`rm ${github_summary}`);
expect(output).toMatch(expected); expect(output).toMatch(expected);
});
});

View file

@ -16,10 +16,12 @@ export async function addSummary() {
await core.summary await core.summary
.addSeparator() .addSeparator()
.addImage( .addRaw(
"https://github.com/step-security/harden-runner/raw/main/images/banner.png", `<p><picture>
"StepSecurity Harden-Runner", <source media="(prefers-color-scheme: light)" srcset="https://github.com/step-security/harden-runner/raw/main/images/banner.png" width="200">
{ width: "200" } <img alt="Dark Banner" src="https://github.com/step-security/harden-runner/raw/main/images/banner-dark.png" width="200">
</picture></p>`,
true
) )
.addLink("View security insights and recommended policy", insights_url) .addLink("View security insights and recommended policy", insights_url)
.addSeparator() .addSeparator()

View file

@ -9,7 +9,6 @@ export interface Configuration {
disable_telemetry: boolean; disable_telemetry: boolean;
disable_sudo: boolean; disable_sudo: boolean;
disable_file_monitoring: boolean; disable_file_monitoring: boolean;
private: string;
} }
export interface PolicyResponse { export interface PolicyResponse {

View file

@ -18,7 +18,7 @@ test("success: fetching policy", async () => {
.get(`/github/${owner}/actions/policies/${policyName}`) .get(`/github/${owner}/actions/policies/${policyName}`)
.reply(200, response); .reply(200, response);
let idToken = "xyz"; let idToken = "xyz";
let policy = await fetchPolicy(owner, policyName, idToken); let policy = await fetchPolicy(owner, policyName, idToken);
console.log(policy); console.log(policy);
expect(policy).toStrictEqual(response); expect(policy).toStrictEqual(response);
@ -36,7 +36,6 @@ test("merge configs", async () => {
disable_telemetry: false, disable_telemetry: false,
disable_sudo: false, disable_sudo: false,
disable_file_monitoring: false, disable_file_monitoring: false,
private: "true",
}; };
let policyResponse: PolicyResponse = { let policyResponse: PolicyResponse = {
owner: "h0x0er", owner: "h0x0er",
@ -59,7 +58,6 @@ test("merge configs", async () => {
disable_telemetry: false, disable_telemetry: false,
disable_sudo: false, disable_sudo: false,
disable_file_monitoring: false, disable_file_monitoring: false,
private: "true",
}; };
localConfig = mergeConfigs(localConfig, policyResponse); localConfig = mergeConfigs(localConfig, policyResponse);

View file

@ -50,7 +50,6 @@ import * as utils from '@actions/cache/lib/internal/cacheUtils'
disable_telemetry: core.getBooleanInput("disable-telemetry"), disable_telemetry: core.getBooleanInput("disable-telemetry"),
disable_sudo: core.getBooleanInput("disable-sudo"), disable_sudo: core.getBooleanInput("disable-sudo"),
disable_file_monitoring: core.getBooleanInput("disable-file-monitoring"), disable_file_monitoring: core.getBooleanInput("disable-file-monitoring"),
private: context.payload.repository.private,
}; };
let policyName = core.getInput("policy"); let policyName = core.getInput("policy");