Skip to content

Commit d41f1c4

Browse files
authored
Security: Harden GitHub workflows and document accepted risks (#13)
Changes: - ci.yml: Add explicit permissions, pin all action SHAs - release.yml: Pin all action SHAs to immutable commits - Add CodeQL config documenting accepted low-risk URL substring alerts Security hardening: - actions/checkout@11bd719 (v4.2.2) - actions/setup-python@a26af69 (v5.6.0) - codecov/codecov-action@18283e0 (v5.4.3) - actions/upload-artifact@ea165f8 (v4.6.2) - actions/download-artifact@d3f86a1 (v4.3.0) - softprops/action-gh-release@da05d55 (v2.2.2) - pypa/gh-action-pypi-publish@76f52bc (v1.12.4) Accepted risks documented in codeql-config.yml: - py/incomplete-url-substring-sanitization: Used for version detection only - py/overly-permissive-file: Test code operating on temp directories
1 parent 7c485c9 commit d41f1c4

3 files changed

Lines changed: 52 additions & 26 deletions

File tree

.github/codeql/codeql-config.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# CodeQL Configuration
2+
# Documentation of alert handling for this repository
3+
4+
name: "CLI Audit CodeQL Config"
5+
6+
# Note: Some alerts are documented as accepted risks:
7+
#
8+
# 1. py/incomplete-url-substring-sanitization in cli_audit/catalog.py
9+
# - These are URL substring checks used for VERSION DETECTION only
10+
# - They determine which API to query for latest versions (npm, pypi, etc.)
11+
# - The package names come from the internal catalog, not user input
12+
# - No installation decisions are made based on these checks
13+
# - Security impact is LOW - worst case is incorrect version lookup
14+
#
15+
# 2. py/overly-permissive-file in tests/test_bulk.py
16+
# - This is TEST CODE operating on temporary directories
17+
# - Testing permission handling and error recovery
18+
# - Using 0o755 on temp dir is appropriate for test cleanup
19+
20+
# Query configuration
21+
queries:
22+
- uses: security-extended
23+
- uses: security-and-quality

.github/workflows/ci.yml

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@ on:
77
branches: [main, develop]
88
workflow_dispatch:
99

10+
permissions:
11+
contents: read
12+
1013
jobs:
1114
lint:
1215
name: Lint and Type Check
1316
runs-on: ubuntu-latest
1417

1518
steps:
1619
- name: Checkout code
17-
uses: actions/checkout@v6
20+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
1821

1922
- name: Set up Python
20-
uses: actions/setup-python@v5
23+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
2124
with:
2225
python-version: '3.14'
2326
cache: 'pip'
@@ -48,10 +51,10 @@ jobs:
4851

4952
steps:
5053
- name: Checkout code
51-
uses: actions/checkout@v6
54+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
5255

5356
- name: Set up Python ${{ matrix.python-version }}
54-
uses: actions/setup-python@v5
57+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
5558
with:
5659
python-version: ${{ matrix.python-version }}
5760
cache: 'pip'
@@ -70,7 +73,7 @@ jobs:
7073
pytest tests/integration -v --cov=cli_audit --cov-append --cov-report=xml --cov-report=term
7174
7275
- name: Upload coverage to Codecov
73-
uses: codecov/codecov-action@v5
76+
uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3
7477
with:
7578
file: ./coverage.xml
7679
flags: unittests
@@ -83,10 +86,10 @@ jobs:
8386

8487
steps:
8588
- name: Checkout code
86-
uses: actions/checkout@v6
89+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
8790

8891
- name: Set up Python
89-
uses: actions/setup-python@v5
92+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
9093
with:
9194
python-version: '3.14'
9295

@@ -114,10 +117,10 @@ jobs:
114117

115118
steps:
116119
- name: Checkout code
117-
uses: actions/checkout@v6
120+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
118121

119122
- name: Set up Python
120-
uses: actions/setup-python@v5
123+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
121124
with:
122125
python-version: '3.14'
123126

@@ -135,7 +138,7 @@ jobs:
135138
twine check dist/*
136139
137140
- name: Upload artifacts
138-
uses: actions/upload-artifact@v6
141+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
139142
with:
140143
name: distributions
141144
path: dist/
@@ -146,10 +149,10 @@ jobs:
146149

147150
steps:
148151
- name: Checkout code
149-
uses: actions/checkout@v6
152+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
150153

151154
- name: Set up Python
152-
uses: actions/setup-python@v5
155+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
153156
with:
154157
python-version: '3.14'
155158

@@ -171,10 +174,10 @@ jobs:
171174

172175
steps:
173176
- name: Checkout code
174-
uses: actions/checkout@v6
177+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
175178

176179
- name: Set up Python
177-
uses: actions/setup-python@v5
180+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
178181
with:
179182
python-version: '3.14'
180183

@@ -190,4 +193,4 @@ jobs:
190193
191194
- name: Test programmatic API
192195
run: |
193-
python -c "from cli_audit import Config, Environment, load_config; c = Config(); print('API works')"
196+
python -c "from cli_audit import Config, Environment, load_config; c = Config(); print('API works')"

.github/workflows/release.yml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ jobs:
1616

1717
steps:
1818
- name: Checkout code
19-
uses: actions/checkout@v6
19+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
2020

2121
- name: Set up Python
22-
uses: actions/setup-python@v5
22+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
2323
with:
2424
python-version: '3.14'
2525

@@ -37,7 +37,7 @@ jobs:
3737
twine check dist/*
3838
3939
- name: Upload artifacts
40-
uses: actions/upload-artifact@v6
40+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
4141
with:
4242
name: distributions
4343
path: dist/
@@ -49,10 +49,10 @@ jobs:
4949

5050
steps:
5151
- name: Checkout code
52-
uses: actions/checkout@v6
52+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
5353

5454
- name: Download artifacts
55-
uses: actions/download-artifact@v7
55+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
5656
with:
5757
name: distributions
5858
path: dist/
@@ -71,13 +71,13 @@ jobs:
7171
sed -n "/^## \[${VERSION}\]/,/^## \[/p" CHANGELOG.md | sed '$d' >> $GITHUB_OUTPUT || echo "See CHANGELOG.md for details" >> $GITHUB_OUTPUT
7272
echo "EOF" >> $GITHUB_OUTPUT
7373
else
74-
echo "CHANGES=Release ${{ steps.version.outputs.VERSION }}" >> $GITHUB_OUTPUT
74+
echo "CHANGES=Release ${VERSION}" >> $GITHUB_OUTPUT
7575
fi
7676
env:
7777
VERSION: ${{ steps.version.outputs.VERSION }}
7878

7979
- name: Create Release
80-
uses: softprops/action-gh-release@v2
80+
uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2
8181
with:
8282
files: dist/*
8383
body: ${{ steps.changelog.outputs.CHANGES }}
@@ -94,13 +94,13 @@ jobs:
9494

9595
steps:
9696
- name: Download artifacts
97-
uses: actions/download-artifact@v7
97+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
9898
with:
9999
name: distributions
100100
path: dist/
101101

102102
- name: Publish to PyPI
103-
uses: pypa/gh-action-pypi-publish@release/v1
103+
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
104104
with:
105105
password: ${{ secrets.PYPI_API_TOKEN }}
106106
skip-existing: true
@@ -113,13 +113,13 @@ jobs:
113113

114114
steps:
115115
- name: Download artifacts
116-
uses: actions/download-artifact@v7
116+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
117117
with:
118118
name: distributions
119119
path: dist/
120120

121121
- name: Publish to Test PyPI
122-
uses: pypa/gh-action-pypi-publish@release/v1
122+
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4
123123
with:
124124
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
125125
repository-url: https://test.pypi.org/legacy/

0 commit comments

Comments
 (0)