Skip to content

Commit 7f7bc77

Browse files
authored
πŸ‘·β€β™‚οΈ Harden GitHub Actions Workflows (#383)
### πŸ•“ Changelog This PR hardens the `xdeployer`'s GitHub Actions workflows _end to end_. Every workflow now _defaults_ to `permissions: {}`, with minimal grants added per job, a `timeout-minutes` bound on every job, and `persist-credentials: false` on all checkout steps. Third-party actions and selected tooling dependencies are pinned to immutable commit `SHA`s or exact versions instead of mutable tags, and the `npm` publish script now runs under `set -Eeuo pipefail` with quoted variables. The CodeQL workflow switches to explicit `build-mode: none`, dropping the now-redundant Autobuild step. These workflow changes are backed by three repository settings updates: "_Require actions to be pinned to a full-length commit SHA_" is now enabled, the default workflow permissions are restricted to "_Read repository contents and packages permissions_" only, and "_Allow GitHub Actions to create and approve pull requests_" is now disabled. --------- Signed-off-by: pcaversaccio <pascal.caversaccio@hotmail.ch>
1 parent a4ed3d1 commit 7f7bc77

7 files changed

Lines changed: 169 additions & 116 deletions

File tree

β€Ž.github/dependabot.ymlβ€Ž

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,22 @@ updates:
1010
- "dependencies πŸ”"
1111
assignees:
1212
- "pcaversaccio"
13+
groups:
14+
npm-dependencies:
15+
patterns:
16+
- "*"
17+
18+
- package-ecosystem: "github-actions"
19+
directory: "/"
20+
schedule:
21+
interval: "weekly"
22+
day: "monday"
23+
target-branch: "main"
24+
labels:
25+
- "dependencies πŸ”"
26+
assignees:
27+
- "pcaversaccio"
28+
groups:
29+
github-actions-dependencies:
30+
patterns:
31+
- "*"

β€Ž.github/workflows/checks.ymlβ€Ž

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ concurrency:
66
group: ${{ github.workflow }}-${{ github.ref }}
77
cancel-in-progress: true
88

9+
permissions: {}
10+
911
jobs:
1012
prettify-n-lint:
1113
runs-on: ${{ matrix.os }}
14+
timeout-minutes: 15
15+
permissions:
16+
contents: read
1217
strategy:
1318
matrix:
1419
os:
@@ -18,10 +23,12 @@ jobs:
1823

1924
steps:
2025
- name: Checkout
21-
uses: actions/checkout@v7
26+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
27+
with:
28+
persist-credentials: false
2229

2330
- name: Install pnpm
24-
uses: pnpm/action-setup@v6
31+
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
2532
with:
2633
run_install: false
2734

@@ -30,16 +37,15 @@ jobs:
3037
run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
3138

3239
- name: Restore pnpm cache
33-
uses: actions/cache@v6
40+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
3441
id: pnpm-cache
3542
with:
3643
path: ${{ steps.pnpm-cache-dir-path.outputs.dir }}
3744
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
38-
restore-keys: |
39-
${{ runner.os }}-pnpm-store-
45+
restore-keys: ${{ runner.os }}-pnpm-store-
4046

4147
- name: Use Node.js ${{ matrix.node_version }}
42-
uses: actions/setup-node@v6
48+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
4349
with:
4450
node-version: ${{ matrix.node_version }}
4551

@@ -51,24 +57,32 @@ jobs:
5157

5258
codespell:
5359
runs-on: ${{ matrix.os }}
60+
timeout-minutes: 5
61+
permissions:
62+
contents: read
5463
strategy:
5564
matrix:
5665
os:
5766
- ubuntu-latest
5867

5968
steps:
6069
- name: Checkout
61-
uses: actions/checkout@v7
70+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
71+
with:
72+
persist-credentials: false
6273

6374
- name: Run codespell
64-
uses: codespell-project/actions-codespell@v2
75+
uses: codespell-project/actions-codespell@8f01853be192eb0f849a5c7d721450e7a467c579 # v2.2.0
6576
with:
6677
check_filenames: true
6778
skip: ./.git,pnpm-lock.yaml
6879
ignore_words_list: superseed
6980

7081
validate-links:
7182
runs-on: ${{ matrix.os }}
83+
timeout-minutes: 20
84+
permissions:
85+
contents: read
7286
strategy:
7387
matrix:
7488
os:
@@ -78,16 +92,18 @@ jobs:
7892

7993
steps:
8094
- name: Checkout
81-
uses: actions/checkout@v7
95+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
96+
with:
97+
persist-credentials: false
8298

8399
- name: Set up Ruby
84-
uses: ruby/setup-ruby@v1
100+
uses: ruby/setup-ruby@0dafeac902942906541bc140009cdbf32665b601 # v1.315.0
85101
with:
86102
ruby-version: ${{ matrix.ruby_version }}
87103
bundler-cache: true
88104

89105
- name: Install awesome_bot
90-
run: gem install awesome_bot
106+
run: gem install awesome_bot -v 1.20.0
91107

92108
- name: Validate URLs
93109
run: |

β€Ž.github/workflows/codeql.ymlβ€Ž

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,38 @@ concurrency:
66
group: ${{ github.workflow }}-${{ github.ref }}
77
cancel-in-progress: true
88

9+
permissions: {}
10+
911
jobs:
1012
analyse:
1113
runs-on: ${{ matrix.os }}
14+
timeout-minutes: 20
1215
permissions:
16+
contents: read
1317
security-events: write
1418
strategy:
1519
matrix:
1620
os:
1721
- ubuntu-latest
1822
language:
1923
- javascript-typescript
24+
build-mode:
25+
- none
2026

2127
steps:
2228
- name: Checkout
23-
uses: actions/checkout@v7
29+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
30+
with:
31+
persist-credentials: false
2432

2533
- name: Initialise CodeQL
26-
uses: github/codeql-action/init@v4
34+
uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
2735
with:
2836
languages: ${{ matrix.language }}
37+
build-mode: ${{ matrix.build-mode }}
2938
queries: +security-and-quality
3039

31-
- name: Autobuild
32-
uses: github/codeql-action/autobuild@v4
33-
3440
- name: Perform CodeQL analysis
35-
uses: github/codeql-action/analyze@v4
41+
uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
3642
with:
3743
category: "/language:${{ matrix.language }}"

β€Ž.github/workflows/publish-npm.ymlβ€Ž

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@ on:
55
types: [published]
66
workflow_dispatch:
77

8+
permissions: {}
9+
810
jobs:
911
publish:
1012
runs-on: ${{ matrix.os }}
13+
timeout-minutes: 10
14+
permissions:
15+
contents: read
16+
id-token: write
1117
environment:
1218
name: npm
1319
url: https://npmjs.com/package/xdeployer
14-
permissions:
15-
id-token: write
1620
strategy:
1721
matrix:
1822
os:
@@ -22,10 +26,12 @@ jobs:
2226

2327
steps:
2428
- name: Checkout
25-
uses: actions/checkout@v7
29+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
30+
with:
31+
persist-credentials: false
2632

2733
- name: Install pnpm
28-
uses: pnpm/action-setup@v6
34+
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
2935
with:
3036
run_install: false
3137

@@ -34,16 +40,15 @@ jobs:
3440
run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
3541

3642
- name: Restore pnpm cache
37-
uses: actions/cache@v6
43+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
3844
id: pnpm-cache
3945
with:
4046
path: ${{ steps.pnpm-cache-dir-path.outputs.dir }}
4147
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
42-
restore-keys: |
43-
${{ runner.os }}-pnpm-store-
48+
restore-keys: ${{ runner.os }}-pnpm-store-
4449

4550
- name: Setup .npmrc file to publish to npm
46-
uses: actions/setup-node@v6
51+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
4752
with:
4853
node-version: ${{ matrix.node_version }}
4954
registry-url: "https://registry.npmjs.org"
@@ -53,11 +58,12 @@ jobs:
5358

5459
- name: Publish to npm
5560
run: |
61+
set -Eeuo pipefail
5662
VERSION=$(node -p "require('./package.json').version")
57-
case $VERSION in
63+
case "$VERSION" in
5864
*-alpha.*) TAG="alpha" ;;
5965
*-beta.*) TAG="beta" ;;
6066
*-rc.*) TAG="next" ;;
6167
*) TAG="latest" ;;
6268
esac
63-
pnpm publish --no-git-checks --tag $TAG
69+
pnpm publish --no-git-checks --tag "$TAG"

β€Ž.github/workflows/test.ymlβ€Ž

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ concurrency:
66
group: ${{ github.workflow }}-${{ github.ref }}
77
cancel-in-progress: true
88

9+
permissions: {}
10+
911
jobs:
1012
tests:
1113
runs-on: ${{ matrix.os }}
14+
timeout-minutes: 15
15+
permissions:
16+
contents: read
1217
strategy:
1318
matrix:
1419
os:
@@ -18,10 +23,12 @@ jobs:
1823

1924
steps:
2025
- name: Checkout
21-
uses: actions/checkout@v7
26+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
27+
with:
28+
persist-credentials: false
2229

2330
- name: Install pnpm
24-
uses: pnpm/action-setup@v6
31+
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
2532
with:
2633
run_install: false
2734

@@ -30,16 +37,15 @@ jobs:
3037
run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
3138

3239
- name: Restore pnpm cache
33-
uses: actions/cache@v6
40+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
3441
id: pnpm-cache
3542
with:
3643
path: ${{ steps.pnpm-cache-dir-path.outputs.dir }}
3744
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
38-
restore-keys: |
39-
${{ runner.os }}-pnpm-store-
45+
restore-keys: ${{ runner.os }}-pnpm-store-
4046

4147
- name: Use Node.js ${{ matrix.node_version }}
42-
uses: actions/setup-node@v6
48+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
4349
with:
4450
node-version: ${{ matrix.node_version }}
4551

β€Žpackage.jsonβ€Ž

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,24 @@
4343
"README.md"
4444
],
4545
"devDependencies": {
46-
"@eslint/js": "^10.0.1",
47-
"@nomicfoundation/hardhat-ethers": "^3.1.3",
48-
"@types/chai": "^4.3.20",
49-
"@types/fs-extra": "^11.0.4",
50-
"@types/mocha": "^10.0.10",
51-
"@types/node": "^26.0.0",
52-
"chai": "^4.5.0",
53-
"eslint": "^10.5.0",
54-
"eslint-config-prettier": "^10.1.8",
55-
"ethers": "^6.17.0",
56-
"globals": "^17.7.0",
57-
"hardhat": "^2.28.6",
58-
"mocha": "^11.7.6",
59-
"prettier": "^3.8.4",
60-
"prettier-plugin-solidity": "^2.3.1",
61-
"ts-node": "^10.9.2",
62-
"typescript": "^6.0.3",
63-
"typescript-eslint": "^8.62.0"
46+
"@eslint/js": "10.0.1",
47+
"@nomicfoundation/hardhat-ethers": "3.1.3",
48+
"@types/chai": "4.3.20",
49+
"@types/fs-extra": "11.0.4",
50+
"@types/mocha": "10.0.10",
51+
"@types/node": "26.0.0",
52+
"chai": "4.5.0",
53+
"eslint": "10.5.0",
54+
"eslint-config-prettier": "10.1.8",
55+
"ethers": "6.17.0",
56+
"globals": "17.7.0",
57+
"hardhat": "2.28.6",
58+
"mocha": "11.7.6",
59+
"prettier": "3.8.4",
60+
"prettier-plugin-solidity": "2.3.1",
61+
"ts-node": "10.9.2",
62+
"typescript": "6.0.3",
63+
"typescript-eslint": "8.62.0"
6464
},
6565
"peerDependencies": {
6666
"@nomicfoundation/hardhat-ethers": "^3.1.3",

0 commit comments

Comments
Β (0)