Skip to content

Commit f3f81f0

Browse files
chore: harden CI with Semgrep, CodeQL, pip-audit, SHA-pinned actions, and contributor tooling
- SHA-pin all GitHub Actions across all workflows (ci, scorecard, benchmark) - Add Semgrep SAST workflow (p/python + p/owasp-top-ten, SARIF upload) - Add CodeQL workflow (python + actions, security-extended queries) - Add pip-audit security job to CI; build gates on it - Add concurrency groups with cancel-in-progress to all workflows - Fix scorecard.yml overly broad read-all permissions - Use env var for matrix.python-version (hardened shell interpolation) - Add Dependabot config with reviewers for pip and github-actions - Add PR template with security review checklist - Add FUNDING.yml, Ruff badge, pre-commit large-file and merge-conflict hooks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent c767240 commit f3f81f0

10 files changed

Lines changed: 164 additions & 19 deletions

File tree

.github/FUNDING.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github: [Project-Navi]

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
## Description
2+
3+
<!-- What does this PR do? Why is it needed? -->
4+
5+
## Type of change
6+
7+
- [ ] Bug fix
8+
- [ ] New feature
9+
- [ ] Refactoring
10+
- [ ] Documentation
11+
- [ ] CI / infrastructure
12+
13+
## Checklist
14+
15+
- [ ] Code follows the project's style guidelines
16+
- [ ] Tests added or updated as appropriate
17+
- [ ] No new warnings introduced
18+
- [ ] Security implications reviewed (pipeline ordering, bypass vectors)
19+
20+
## Related issues
21+
22+
<!-- Closes #123 -->

.github/dependabot.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: pip
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
day: monday
8+
commit-message:
9+
prefix: "deps:"
10+
reviewers:
11+
- "ndspence"
12+
groups:
13+
dev-dependencies:
14+
dependency-type: development
15+
16+
- package-ecosystem: github-actions
17+
directory: /
18+
schedule:
19+
interval: weekly
20+
day: monday
21+
commit-message:
22+
prefix: "ci:"
23+
reviewers:
24+
- "ndspence"
25+
groups:
26+
actions:
27+
patterns: ["*"]

.github/workflows/benchmark.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,23 @@ on:
66
permissions:
77
contents: read
88

9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
913
jobs:
1014
benchmark:
1115
runs-on: ubuntu-latest
1216
steps:
13-
- uses: actions/checkout@v4
14-
- uses: astral-sh/setup-uv@v7
17+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
1519
with:
1620
enable-cache: true
1721
- name: Install dependencies
1822
run: uv sync --frozen
1923
- name: Run benchmarks
2024
run: uv run pytest tests/test_benchmark.py -v
21-
- uses: actions/upload-artifact@v4
25+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
2226
with:
2327
name: benchmarks
2428
path: .benchmarks/

.github/workflows/ci.yml

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,16 @@ on:
99
permissions:
1010
contents: read
1111

12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
1216
jobs:
1317
lint:
1418
runs-on: ubuntu-latest
1519
steps:
16-
- uses: actions/checkout@v4
17-
- uses: astral-sh/setup-uv@v7
20+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
21+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
1822
with:
1923
enable-cache: true
2024
- name: Install dependencies
@@ -27,8 +31,8 @@ jobs:
2731
typecheck:
2832
runs-on: ubuntu-latest
2933
steps:
30-
- uses: actions/checkout@v4
31-
- uses: astral-sh/setup-uv@v7
34+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
35+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
3236
with:
3337
enable-cache: true
3438
- name: Install dependencies
@@ -43,21 +47,35 @@ jobs:
4347
matrix:
4448
python-version: ["3.12", "3.13"]
4549
steps:
46-
- uses: actions/checkout@v4
47-
- uses: astral-sh/setup-uv@v7
50+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
51+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
4852
with:
4953
enable-cache: true
5054
- name: Install dependencies
51-
run: uv sync --frozen --python ${{ matrix.python-version }}
55+
env:
56+
PYTHON_VERSION: ${{ matrix.python-version }}
57+
run: uv sync --frozen --python "$PYTHON_VERSION"
5258
- name: Run tests
5359
run: uv run pytest tests/ -v --benchmark-disable
5460

61+
security:
62+
runs-on: ubuntu-latest
63+
steps:
64+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
65+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
66+
with:
67+
enable-cache: true
68+
- name: Install dependencies
69+
run: uv sync --frozen
70+
- name: pip-audit
71+
run: uvx pip-audit==2.9.0
72+
5573
build:
56-
needs: [lint, typecheck, test]
74+
needs: [lint, typecheck, test, security]
5775
runs-on: ubuntu-latest
5876
steps:
59-
- uses: actions/checkout@v4
60-
- uses: astral-sh/setup-uv@v7
77+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
78+
- uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0
6179
with:
6280
enable-cache: true
6381
- name: Build wheel
@@ -72,7 +90,7 @@ jobs:
7290
assert walk({'k': 'v'}) == {'k': 'v'}
7391
print('Smoke test passed')
7492
"
75-
- uses: actions/upload-artifact@v4
93+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
7694
with:
7795
name: wheel
7896
path: dist/*.whl

.github/workflows/codeql.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: CodeQL
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
schedule:
9+
- cron: "30 5 * * 1" # Monday 05:30 UTC
10+
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
permissions:
16+
contents: read
17+
security-events: write
18+
19+
jobs:
20+
analyze:
21+
runs-on: ubuntu-latest
22+
strategy:
23+
fail-fast: false
24+
matrix:
25+
language: [python, actions]
26+
steps:
27+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
28+
- name: Initialize CodeQL
29+
uses: github/codeql-action/init@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
30+
with:
31+
languages: ${{ matrix.language }}
32+
queries: +security-extended
33+
- name: Autobuild
34+
uses: github/codeql-action/autobuild@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
35+
- name: Perform CodeQL Analysis
36+
uses: github/codeql-action/analyze@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
37+
with:
38+
category: "/language:${{ matrix.language }}"

.github/workflows/scorecard.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ on:
66
push:
77
branches: [main]
88

9-
permissions: read-all
9+
permissions:
10+
contents: read
1011

1112
jobs:
1213
scorecard:
@@ -18,25 +19,25 @@ jobs:
1819

1920
steps:
2021
- name: Checkout
21-
uses: actions/checkout@v4
22+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2223
with:
2324
persist-credentials: false
2425

2526
- name: Run Scorecard
26-
uses: ossf/scorecard-action@v2.4.3
27+
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
2728
with:
2829
results_file: results.sarif
2930
results_format: sarif
3031
publish_results: true
3132

3233
- name: Upload artifact
33-
uses: actions/upload-artifact@v4
34+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
3435
with:
3536
name: SARIF file
3637
path: results.sarif
3738
retention-days: 5
3839

3940
- name: Upload to code-scanning
40-
uses: github/codeql-action/upload-sarif@v3
41+
uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
4142
with:
4243
sarif_file: results.sarif

.github/workflows/semgrep.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Semgrep SAST
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
security-events: write
12+
13+
concurrency:
14+
group: ${{ github.workflow }}-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
jobs:
18+
semgrep:
19+
runs-on: ubuntu-latest
20+
container:
21+
image: semgrep/semgrep:1.152.0
22+
steps:
23+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
24+
- name: Run Semgrep
25+
run: semgrep scan --config p/python --config p/owasp-top-ten --sarif -o semgrep.sarif .
26+
- name: Upload SARIF
27+
uses: github/codeql-action/upload-sarif@89a39a4e59826350b863aa6b6252a07ad50cf83e # v4.32.4
28+
if: always()
29+
with:
30+
sarif_file: semgrep.sarif

.pre-commit-config.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ repos:
66
- id: end-of-file-fixer
77
- id: check-yaml
88
- id: check-toml
9+
- id: check-added-large-files
10+
args: [--maxkb=1024]
11+
- id: check-merge-conflict
912

1013
- repo: https://github.com/astral-sh/ruff-pre-commit
1114
rev: v0.15.4

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
55
[![Python 3.12+](https://img.shields.io/badge/Python-3.12%2B-green.svg)](https://www.python.org/)
66
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Project-Navi/navi-sanitize/badge)](https://scorecard.dev/viewer/?uri=github.com/Project-Navi/navi-sanitize)
7+
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
78

89
Input sanitization pipeline for untrusted text. Bytes in, clean bytes out.
910

0 commit comments

Comments
 (0)