Skip to content

Commit 876b113

Browse files
authored
chore: set explicit workflow permissions and pin down actions (#2090)
Signed-off-by: tdruez <tdruez@aboutcode.org>
1 parent 79d7927 commit 876b113

17 files changed

Lines changed: 202 additions & 104 deletions

.github/workflows/generate-sboms.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ env:
1212
jobs:
1313
generate-sboms:
1414
runs-on: ubuntu-24.04
15+
permissions:
16+
contents: read
1517

1618
steps:
17-
- name: Checkout code
18-
uses: actions/checkout@v4
19+
- name: Checkout repository
20+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
21+
with:
22+
persist-credentials: false # do not keep the token around
1923

2024
- name: Ensure INPUTS_PATH directory exists
2125
run: mkdir -p "${{ env.INPUTS_PATH }}"
@@ -32,7 +36,7 @@ jobs:
3236
find scancodeio/ -type f -name "*.ABOUT" -exec cp {} "${{ env.INPUTS_PATH }}/about-files/" \;
3337
3438
- name: Resolve the dependencies using ScanCode-action
35-
uses: aboutcode-org/scancode-action@main
39+
uses: aboutcode-org/scancode-action@8adbf888f487c3cdf6c15386035769cd03a94c66
3640
with:
3741
pipelines: "resolve_dependencies:DynamicResolver"
3842
inputs-path: ${{ env.INPUTS_PATH }}

.github/workflows/pr-quality.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ permissions:
66
pull-requests: write
77

88
on:
9+
# pull_request_target is required so the action can close/comment on fork PRs.
10+
# This is safe because: no untrusted code is checked out, and no attacker-controlled
11+
# values are interpolated into shell commands. All action inputs are hardcoded.
912
pull_request_target:
1013
types: [opened, reopened]
1114

@@ -14,7 +17,7 @@ jobs:
1417
runs-on: ubuntu-24.04
1518
name: Detects and automatically closes low-quality and AI slop PRs
1619
steps:
17-
- uses: peakoss/anti-slop@v0
20+
- uses: peakoss/anti-slop@e158eeefe5c43e1d3ba8533b84e0e35d9d6761de
1821
with:
1922
# Number of check failures needed before failure actions are triggered
2023
max-failures: 3

.github/workflows/publish-docker-image.yml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,19 @@ jobs:
2222
permissions:
2323
contents: read
2424
packages: write
25+
attestations: write
26+
id-token: write
2527

2628
steps:
2729
- name: Checkout repository
28-
uses: actions/checkout@v4
30+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
31+
with:
32+
persist-credentials: false # do not keep the token around
2933

3034
# Uses the `docker/login-action` action to log in to the Container registry using
3135
# the account and password that will publish the packages.
3236
- name: Log in to the Container registry
33-
uses: docker/login-action@v3
37+
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
3438
with:
3539
registry: ${{ env.REGISTRY }}
3640
username: ${{ github.actor }}
@@ -42,7 +46,7 @@ jobs:
4246
# The `images` value provides the base name for the tags and labels.
4347
- name: Extract metadata (tags, labels) for Docker
4448
id: meta
45-
uses: docker/metadata-action@v5
49+
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
4650
with:
4751
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
4852

@@ -53,11 +57,22 @@ jobs:
5357
# It uses the `tags` and `labels` parameters to tag and label the image with
5458
# the output from the "meta" step.
5559
- name: Build and push Docker image
56-
uses: docker/build-push-action@v5
60+
id: push
61+
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
5762
with:
5863
context: .
5964
push: true
6065
tags: |
6166
${{ steps.meta.outputs.tags }}
62-
${{ env.REGISTRY }}/aboutcode-org/scancode.io:latest
67+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
6368
labels: ${{ steps.meta.outputs.labels }}
69+
70+
# This step generates an artifact attestation for the image, which is an
71+
# unforgeable statement about where and how it was built.
72+
# It increases supply chain security for people who consume the image.
73+
- name: Generate artifact attestation
74+
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
75+
with:
76+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
77+
subject-digest: ${{ steps.push.outputs.digest }}
78+
push-to-registry: true

.github/workflows/publish-pypi-release-aboutcode-pipeline.yml

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,56 @@ on:
77
- "aboutcode.pipeline/*"
88

99
jobs:
10-
build-and-publish:
10+
build:
1111
name: Build and publish library to PyPI
1212
runs-on: ubuntu-24.04
13+
permissions:
14+
contents: read
1315

1416
steps:
15-
- uses: actions/checkout@v4
17+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
with:
19+
persist-credentials: false # do not keep the token around
1620

1721
- name: Set up Python
18-
uses: actions/setup-python@v5
22+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
1923
with:
2024
python-version: 3.14
2125

2226
- name: Install flot
23-
run: python -m pip install flot --user
27+
run: python -m pip install flot==0.7.2 --user
2428

2529
- name: Build a binary wheel and a source tarball
2630
run: python -m flot --pyproject pipeline-pyproject.toml --sdist --wheel --output-dir dist/
2731

28-
- name: Publish to PyPI
29-
if: startsWith(github.ref, 'refs/tags')
30-
uses: pypa/gh-action-pypi-publish@release/v1
32+
- name: Upload package distributions as GitHub workflow artifacts
33+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
3134
with:
32-
password: ${{ secrets.PYPI_API_TOKEN_ABOUTCODE_PIPELINE }}
35+
name: python-package-distributions
36+
path: dist/
37+
38+
# Only set the id-token: write permission in the job that does publishing, not globally.
39+
# Also, separate building from publishing — this makes sure that any scripts
40+
# maliciously injected into the build or test environment won't be able to elevate
41+
# privileges while flying under the radar.
42+
pypi-publish:
43+
name: Upload package distributions to PyPI
44+
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
45+
needs:
46+
- build
47+
runs-on: ubuntu-24.04
48+
environment:
49+
name: pypi
50+
url: https://pypi.org/p/aboutcode.pipeline
51+
permissions:
52+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
3353

34-
- name: Upload built archives
35-
uses: actions/upload-artifact@v4
54+
steps:
55+
- name: Download all the dists
56+
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
3657
with:
37-
name: pypi_archives
38-
path: dist/*
58+
name: python-package-distributions
59+
path: dist/
60+
61+
- name: Publish to PyPI
62+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,86 @@
1-
name: Build Python distributions and publish on PyPI
1+
name: Build Python distributions, publish on PyPI, and create a GH release
22

33
on:
44
workflow_dispatch:
55
push:
66
tags:
77
- "v*.*.*"
88

9+
env:
10+
PYPI_PROJECT_URL: "https://pypi.org/p/scancodeio"
11+
912
jobs:
10-
build-and-publish:
11-
name: Build and publish library to PyPI
13+
build-python-dist:
14+
name: Build Python distributions
1215
runs-on: ubuntu-24.04
16+
permissions:
17+
contents: read
1318

1419
steps:
15-
- uses: actions/checkout@v4
20+
- name: Checkout repository
21+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
22+
with:
23+
persist-credentials: false # do not keep the token around
1624

1725
- name: Set up Python
18-
uses: actions/setup-python@v5
26+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
1927
with:
2028
python-version: 3.14
2129

2230
- name: Install pypa/build
2331
run: python -m pip install build --user
2432

2533
- name: Build a binary wheel and a source tarball
26-
run: python -m build --sdist --wheel --outdir dist/ .
34+
run: python -m build --sdist --wheel --outdir dist/
2735

28-
- name: Publish to PyPI
29-
if: startsWith(github.ref, 'refs/tags')
30-
uses: pypa/gh-action-pypi-publish@release/v1
36+
- name: Upload package distributions as GitHub workflow artifacts
37+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
3138
with:
32-
password: ${{ secrets.PYPI_API_TOKEN }}
39+
name: python-package-distributions
40+
path: dist/
3341

34-
- name: Upload built archives
35-
uses: actions/upload-artifact@v4
42+
# Only set the id-token: write permission in the job that does publishing, not globally.
43+
# Also, separate building from publishing — this makes sure that any scripts
44+
# maliciously injected into the build or test environment won't be able to elevate
45+
# privileges while flying under the radar.
46+
pypi-publish:
47+
name: Upload package distributions to PyPI
48+
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
49+
needs:
50+
- build-python-dist
51+
runs-on: ubuntu-24.04
52+
environment:
53+
name: pypi
54+
url: ${{ env.PYPI_PROJECT_URL }}
55+
permissions:
56+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
57+
58+
steps:
59+
- name: Download package distributions
60+
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
3661
with:
37-
name: pypi_archives
38-
path: dist/*
62+
name: python-package-distributions
63+
path: dist/
3964

40-
- name: Create a GitHub release
41-
uses: softprops/action-gh-release@v2
65+
- name: Publish to PyPI
66+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
67+
68+
create-gh-release:
69+
name: Create GitHub release
70+
needs:
71+
- build-python-dist
72+
runs-on: ubuntu-24.04
73+
permissions:
74+
contents: write
75+
76+
steps:
77+
- name: Download package distributions
78+
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
4279
with:
43-
generate_release_notes: true
44-
draft: false
45-
files: dist/*
80+
name: python-package-distributions
81+
path: dist/
82+
83+
- name: Create GitHub release
84+
run: gh release create "$GITHUB_REF_NAME" dist/* --generate-notes
85+
env:
86+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/run-unit-tests-docker.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ jobs:
1515
runs-on: ubuntu-24.04
1616

1717
steps:
18-
- name: Checkout code
19-
uses: actions/checkout@v4
18+
- name: Checkout repository
19+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
20+
with:
21+
persist-credentials: false # do not keep the token around
2022

2123
- name: Generate the .env file and the SECRET_KEY
2224
run: make envfile

.github/workflows/run-unit-tests-macos.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,18 @@ jobs:
2424
python-version: ["3.12", "3.13", "3.14"]
2525

2626
steps:
27-
- name: Checkout code
28-
uses: actions/checkout@v4
27+
- name: Checkout repository
28+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
29+
with:
30+
persist-credentials: false # do not keep the token around
2931

3032
- name: Set up Python ${{ matrix.python-version }}
31-
uses: actions/setup-python@v5
33+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
3234
with:
3335
python-version: ${{ matrix.python-version }}
3436

3537
- name: Set up PostgreSQL
36-
uses: ikalnytskyi/action-setup-postgres@v8
38+
uses: ikalnytskyi/action-setup-postgres@c4dda34aae1c821e3a771b68b73b13af3198a7ee # v8
3739
with:
3840
postgres-version: "17"
3941
database: ${{ env.POSTGRES_DB }}

.github/workflows/run-unit-tests.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222

2323
services:
2424
postgres:
25-
image: postgres:17
25+
image: postgres:17.9
2626
env:
2727
POSTGRES_DB: ${{ env.POSTGRES_DB }}
2828
POSTGRES_USER: ${{ env.POSTGRES_USER }}
@@ -42,11 +42,13 @@ jobs:
4242
python-version: ["3.12", "3.13", "3.14"]
4343

4444
steps:
45-
- name: Checkout code
46-
uses: actions/checkout@v4
45+
- name: Checkout repository
46+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
47+
with:
48+
persist-credentials: false # do not keep the token around
4749

4850
- name: Set up Python ${{ matrix.python-version }}
49-
uses: actions/setup-python@v5
51+
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
5052
with:
5153
python-version: ${{ matrix.python-version }}
5254

.github/workflows/sca-integration-anchore.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@ jobs:
2828
runs-on: ubuntu-24.04
2929
steps:
3030
- name: Generate CycloneDX SBOM with Anchore Grype scanner
31-
uses: anchore/scan-action@v6
31+
uses: anchore/scan-action@7037fa011853d5a11690026fb85feee79f4c946c # v7.3.2
3232
with:
3333
image: ${{ env.IMAGE_REFERENCE }}
3434
output-format: cyclonedx-json
3535
output-file: "anchore-grype-sbom.cdx.json"
3636
fail-build: false
3737

3838
- name: Upload SBOM as GitHub Artifact
39-
uses: actions/upload-artifact@v4
39+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
4040
with:
4141
name: anchore-sbom-report
4242
path: "anchore-grype-sbom.cdx.json"
4343
retention-days: 20
4444

4545
- name: Import SBOM into ScanCode.io
46-
uses: aboutcode-org/scancode-action@main
46+
uses: aboutcode-org/scancode-action@8adbf888f487c3cdf6c15386035769cd03a94c66
4747
with:
4848
pipelines: "load_sbom"
4949
inputs-path: "anchore-grype-sbom.cdx.json"

.github/workflows/sca-integration-cdxgen.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
runs-on: ubuntu-24.04
2929
steps:
3030
- name: Install CycloneDX cdxgen
31-
run: npm install @cyclonedx/cdxgen
31+
run: npm install @cyclonedx/cdxgen@12.1.2
3232

3333
- name: Generate SBOM with CycloneDX cdxgen
3434
run: |
@@ -39,14 +39,14 @@ jobs:
3939
--json-pretty
4040
4141
- name: Upload SBOM as GitHub Artifact
42-
uses: actions/upload-artifact@v4
42+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
4343
with:
4444
name: cdxgen-sbom
4545
path: "cdxgen-sbom.cdx.json"
4646
retention-days: 20
4747

4848
- name: Import SBOM into ScanCode.io
49-
uses: aboutcode-org/scancode-action@main
49+
uses: aboutcode-org/scancode-action@8adbf888f487c3cdf6c15386035769cd03a94c66
5050
with:
5151
pipelines: "load_sbom"
5252
inputs-path: "cdxgen-sbom.cdx.json"

0 commit comments

Comments
 (0)