Skip to content

Commit f179c9f

Browse files
committed
feat: add support for specifying sha256 checksum of downloaded binary
Closes #26 This release adds sha256 checksum support to improve your reproducibility and security posture. Specifying a checksum is not required. To specify a checksum, specify a target in the format: `{owner}/{repository}@{version}:sha256-{checksum}` For example: ```yaml - name: Install flux-capacitor uses: EricCrosson/install-github-release-binary@v2 with: targets: | EricCrosson/hoverboard@11.7.3:sha256-8a4600be96d2ec013209042458ce97a9652fcc46c1c855d0217aa42e330fc06e ```
1 parent b806090 commit f179c9f

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Install multiple binaries:
4747
targets: |
4848
EricCrosson/flux-capacitor@v1
4949
EricCrosson/steam-locomotive@v7.5.3
50-
EricCrosson/hoverboard@7382f9a3ce14be1fd8b3656d262fc2c720c8f51c
50+
EricCrosson/hoverboard@11.7.3:sha256-8a4600be96d2ec013209042458ce97a9652fcc46c1c855d0217aa42e330fc06e
5151
```
5252
5353
## Inputs
@@ -62,12 +62,14 @@ Install multiple binaries:
6262
Specify a whitespace-separated list of targets.
6363

6464
Each target is specified by repo slug and a [semantic version number] using the format `{owner}/{repository}@v{semantic-version}`.
65+
Optionally, include a sha256 checksum.
6566

6667
Examples:
6768

6869
- `EricCrosson/flux-capacitor@v1`
6970
- `EricCrosson/flux-capacitor@v1.2`
7071
- `EricCrosson/flux-capacitor@v1.2.3`
72+
- `EricCrosson/flux-capacitor@v1.2.3:sha256-ad91159c656d427ad8fe5ded2946f29f3a612c6b7a4af6129e9aa85256b7299e`
7173

7274
[semantic version number]: https://semver.org/
7375

src/index.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { createHash } from "node:crypto";
12
import { arch, platform } from "node:os";
23
import * as fs from "node:fs";
34
import * as path from "node:path";
@@ -23,6 +24,7 @@ import type {
2324
RepositorySlug,
2425
TargetRelease,
2526
} from "./types";
27+
import { isSome } from "./option";
2628

2729
function getDestinationDirectory(
2830
storageDirectory: string,
@@ -105,6 +107,27 @@ async function installGitHubReleaseBinary(
105107
}
106108
}
107109

110+
// No matter where the binary was sourced from, ensure it matches the
111+
// expected checksum
112+
if (isSome(targetRelease.checksum)) {
113+
const fileBuffer = fs.readFileSync(destinationFilename);
114+
const hash = createHash("sha256");
115+
hash.update(fileBuffer);
116+
const calculatedChecksum = hash.digest("hex");
117+
const expectedChecksum = targetRelease.checksum.value;
118+
if (calculatedChecksum !== expectedChecksum) {
119+
const target = `${targetRelease.slug}@${targetRelease.tag}:sha256-${expectedChecksum}`;
120+
console.error(
121+
`Expected checksum ${expectedChecksum}, but got ${calculatedChecksum}`
122+
);
123+
throw new Error(`Unexpected checksum for ${target}`);
124+
} else {
125+
console.debug(
126+
`Calculated checksum ${calculatedChecksum} matches expected checksum ${expectedChecksum}`
127+
);
128+
}
129+
}
130+
108131
// Permissions are an attribute of the filesystem, not the file.
109132
// Set the executable permission on the binary no matter where it came from.
110133
fs.chmodSync(destinationFilename, "755");

0 commit comments

Comments
 (0)