Skip to content

Commit 318c4f9

Browse files
authored
Create sast.yml (#3)
* Create sast.yml * Update scorecard.yml * Update codeql.yml * Update release.yml * Update ci.yml
1 parent a59e964 commit 318c4f9

5 files changed

Lines changed: 162 additions & 43 deletions

File tree

.github/workflows/ci.yml

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,42 @@ name: CI (build & import)
33
on:
44
workflow_dispatch:
55

6+
# Least-privilege token by default
7+
permissions:
8+
contents: read
9+
610
jobs:
711
build-smoke:
812
runs-on: ubuntu-latest
13+
914
steps:
10-
- uses: actions/checkout@v4
15+
- name: Harden runner
16+
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
17+
with:
18+
egress-policy: audit
19+
20+
- name: Checkout
21+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
1122

12-
- uses: actions/setup-python@v6
23+
- name: Set up Python
24+
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6
1325
with:
1426
python-version: "3.12"
1527

28+
# Use pipx to avoid un-hashed pip installs in workflows
29+
- name: Install pipx + build tool (pinned)
30+
run: |
31+
set -euxo pipefail
32+
sudo apt-get update
33+
sudo apt-get install -y pipx
34+
pipx ensurepath
35+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
36+
# build provides the "pyproject-build" console script
37+
pipx install build==1.2.2
38+
1639
- name: Build wheel
1740
run: |
18-
python -m pip install -U pip build setuptools wheel
19-
python -m build
41+
pyproject-build -o dist
2042
2143
- name: Inspect wheel has package files
2244
run: |
@@ -30,10 +52,12 @@ jobs:
3052
assert len(names) > 0, "Wheel missing decision_security/*"
3153
PY
3254
33-
- name: Install & import smoke
55+
- name: Import smoke from wheel (no install)
3456
run: |
35-
python -m pip install dist/*.whl
3657
python - <<'PY'
58+
import glob, sys
59+
whl = glob.glob("dist/*.whl")[0]
60+
sys.path.insert(0, whl) # allow import from wheel zip
3761
from decision_security.synth import sample
3862
print("Smoke OK:", sample("poisson", 5, lam=1.0))
39-
PY
63+
PY

.github/workflows/codeql.yml

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,42 @@ name: CodeQL
22

33
on:
44
push:
5-
branches: [ "master" ]
5+
branches: [ "main" ]
66
pull_request:
7-
branches: [ "master" ]
7+
branches: [ "main" ]
88
schedule:
9-
- cron: "0 3 * * 1" # Mondays 03:00 UTC
10-
workflow_dispatch: {} # to manually trigger the workflow
9+
- cron: "0 3 * * 1"
10+
workflow_dispatch: {}
1111

12+
# Read-only by default
1213
permissions:
1314
contents: read
1415

1516
jobs:
1617
analyze:
17-
name: CodeQL (python)
18+
name: CodeQL (Python)
1819
runs-on: ubuntu-latest
19-
20+
# Only needed to upload SARIF
2021
permissions:
21-
security-events: write # required to upload CodeQL SARIF
22+
contents: read
23+
security-events: write
2224

2325
steps:
26+
- name: Harden runner
27+
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
28+
with:
29+
egress-policy: audit
30+
2431
- name: Checkout
25-
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.2.2
32+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
2633

27-
# CodeQL doesn't need a build step for Python
2834
- name: Initialize CodeQL
29-
uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v3
35+
uses: github/codeql-action/init@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
3036
with:
3137
languages: python
38+
queries: +security-extended
3239

33-
- name: Perform CodeQL Analysis
34-
uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v3
40+
- name: Analyze
41+
uses: github/codeql-action/analyze@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
3542
with:
3643
category: "/language:python"

.github/workflows/release.yml

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,59 @@
1-
name: Publish (PyPI)
1+
name: Release
2+
23
on:
34
push:
4-
tags: ["v*"] # e.g., v0.1.0a1, v0.1.0
5+
tags: [ 'v*.*.*' ]
6+
workflow_dispatch: {}
7+
8+
# Read-only by default
59
permissions:
6-
id-token: write
710
contents: read
11+
812
jobs:
9-
build-and-publish:
13+
build:
1014
runs-on: ubuntu-latest
15+
permissions:
16+
contents: read
1117
steps:
12-
- uses: actions/checkout@v4
13-
- uses: actions/setup-python@v6
14-
with: { python-version: "3.12" }
15-
- run: python -m pip install -U pip build
16-
- run: python -m build
17-
- name: Publish to PyPI
18-
uses: pypa/gh-action-pypi-publish@release/v1
18+
- name: Harden runner
19+
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
1920
with:
20-
verbose: true
21+
egress-policy: audit
22+
23+
- name: Checkout
24+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6
28+
with:
29+
python-version: "3.12"
30+
31+
- name: Build dists
32+
run: |
33+
pip install -U build
34+
python -m build
35+
36+
- name: Upload build artifact
37+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
38+
with:
39+
name: dist
40+
path: dist/*
41+
42+
publish-pypi:
43+
if: ${{ false }} # set to true when ready
44+
needs: build
45+
runs-on: ubuntu-latest
46+
permissions:
47+
contents: read
48+
id-token: write # required only for OIDC-based PyPI publish
49+
steps:
50+
- name: Download build artifact
51+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
52+
with:
53+
name: dist
54+
path: dist
55+
56+
- name: Publish to PyPI (OIDC)
57+
uses: pypa/gh-action-pypi-publish@f8d218034565c4b29629e190f46f5d54e3637bf4 # v1.12.2
58+
with:
59+
print-hash: true

.github/workflows/sast.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: SAST (Semgrep)
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
semgrep:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
security-events: write # needed to upload SARIF
17+
18+
steps:
19+
- name: Harden runner
20+
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
21+
with:
22+
egress-policy: audit
23+
24+
- name: Checkout
25+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
26+
27+
- name: Install pipx + Semgrep (pinned)
28+
run: |
29+
set -euxo pipefail
30+
sudo apt-get update
31+
sudo apt-get install -y pipx
32+
pipx ensurepath
33+
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
34+
pipx install semgrep==1.83.0
35+
semgrep --version
36+
37+
# Note: no --error flag; job will not fail on findings.
38+
- name: Run Semgrep and produce SARIF
39+
run: |
40+
semgrep scan \
41+
--config=p/ci \
42+
--config=p/security-audit \
43+
--metrics=off \
44+
--sarif -o semgrep.sarif
45+
46+
- name: Upload SARIF to Code Scanning
47+
uses: github/codeql-action/upload-sarif@f443b600d91635bebf5b0d9ebc620189c0d6fba5 # v4.30.8
48+
with:
49+
sarif_file: semgrep.sarif
50+
wait-for-processing: true

.github/workflows/scorecard.yml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,39 @@ name: OpenSSF Scorecard
22

33
on:
44
schedule:
5-
- cron: '37 9 * * 2' # Tuesdays 09:37 UTC
5+
- cron: '37 9 * * 2'
66
push:
7-
branches: [ "master" ]
7+
branches: [ "main" ]
88
pull_request:
9-
branches: [ "master" ]
9+
branches: [ "main" ]
1010
workflow_dispatch: {}
1111

12-
# Least privilege by default
12+
# Read-only by default
1313
permissions:
1414
contents: read
1515

1616
jobs:
1717
scorecard:
1818
name: Scorecard analysis
1919
runs-on: ubuntu-latest
20+
# Needs OIDC only to publish results to scorecard.dev
2021
permissions:
2122
contents: read
22-
id-token: write # needed only to publish to scorecard.dev
23+
id-token: write
2324
steps:
2425
- name: Harden runner
2526
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
2627
with:
2728
egress-policy: audit
2829

29-
# No checkout needed for Scorecard itself
3030
- name: Run Scorecard
3131
uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
3232
with:
3333
publish_results: true
3434
results_format: sarif
3535
results_file: results.sarif
3636

37-
# Hand off SARIF to next job (keeps least-privilege here)
38-
- name: Upload SARIF artifact (handoff)
37+
- name: Upload SARIF artifact
3938
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
4039
with:
4140
name: scorecard-sarif
@@ -44,18 +43,18 @@ jobs:
4443

4544
upload-sarif:
4645
name: Upload SARIF to Code Scanning
47-
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork != true
4846
needs: scorecard
4947
runs-on: ubuntu-latest
48+
# Only this job needs to write security events
5049
permissions:
5150
contents: read
52-
security-events: write # confined to this job only
51+
security-events: write
5352
steps:
5453
- name: Checkout (required for fingerprinting)
55-
uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4
54+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
5655

5756
- name: Download SARIF artifact
58-
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v4
57+
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
5958
with:
6059
name: scorecard-sarif
6160
path: .

0 commit comments

Comments
 (0)