Skip to content

Commit a75bd1c

Browse files
committed
security: harden all GitHub Actions workflows and add Nix fallback
- Add SPDX license headers to all workflow files - Add permissions declarations (read-all at workflow level) - Pin all GitHub Actions to full SHA commits for supply chain security - Add flake.nix as Nix fallback per RSR policy (primary: Guix) - Update STATE.scm with detailed roadmap and session history Workflows hardened: - security-policy.yml - guix-nix-policy.yml - scorecard.yml - quality.yml - jekyll-gh-pages.yml - rsr-antipattern.yml - wellknown-enforcement.yml Security verification passed: - No HTTP URLs (HTTPS only) - No weak crypto (MD5/SHA1) - No hardcoded secrets detected
1 parent fce411c commit a75bd1c

9 files changed

Lines changed: 226 additions & 68 deletions

File tree

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
12
name: Guix/Nix Package Policy
23
on: [push, pull_request]
4+
5+
permissions: read-all
6+
37
jobs:
48
check:
59
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
612
steps:
7-
- uses: actions/checkout@v6
13+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
814
- name: Enforce Guix primary / Nix fallback
915
run: |
1016
# Check for package manager files
1117
HAS_GUIX=$(find . -name "*.scm" -o -name ".guix-channel" -o -name "guix.scm" 2>/dev/null | head -1)
1218
HAS_NIX=$(find . -name "*.nix" 2>/dev/null | head -1)
13-
19+
1420
# Block new package-lock.json, yarn.lock, Gemfile.lock, etc.
1521
NEW_LOCKS=$(git diff --name-only --diff-filter=A HEAD~1 2>/dev/null | grep -E 'package-lock\.json|yarn\.lock|Gemfile\.lock|Pipfile\.lock|poetry\.lock|cargo\.lock' || true)
1622
if [ -n "$NEW_LOCKS" ]; then
1723
echo "⚠️ Lock files detected. Prefer Guix manifests for reproducibility."
1824
fi
19-
25+
2026
# Prefer Guix, fallback to Nix
2127
if [ -n "$HAS_GUIX" ]; then
2228
echo "✅ Guix package management detected (primary)"
@@ -25,5 +31,5 @@ jobs:
2531
else
2632
echo "ℹ️ Consider adding guix.scm or flake.nix for reproducible builds"
2733
fi
28-
34+
2935
echo "✅ Package policy check passed"

.github/workflows/jekyll-gh-pages.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
# Sample workflow for building and deploying a Jekyll site to GitHub Pages
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# Deploy Jekyll site to GitHub Pages
23
name: Deploy Jekyll with GitHub Pages dependencies preinstalled
34

45
on:
@@ -27,16 +28,16 @@ jobs:
2728
runs-on: ubuntu-latest
2829
steps:
2930
- name: Checkout
30-
uses: actions/checkout@v6
31+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
3132
- name: Setup Pages
32-
uses: actions/configure-pages@v5
33+
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
3334
- name: Build with Jekyll
34-
uses: actions/jekyll-build-pages@v1
35+
uses: actions/jekyll-build-pages@b178f9334b208360999a0a57b523613563698c66 # v1.0.13
3536
with:
3637
source: ./
3738
destination: ./_site
3839
- name: Upload artifact
39-
uses: actions/upload-pages-artifact@v4
40+
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
4041

4142
# Deployment job
4243
deploy:
@@ -48,4 +49,4 @@ jobs:
4849
steps:
4950
- name: Deploy to GitHub Pages
5051
id: deployment
51-
uses: actions/deploy-pages@v4
52+
uses: actions/deploy-pages@d6db90164e12d9cc034896e2ea8aed2d03feed65 # v4.0.5

.github/workflows/quality.yml

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,55 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
12
name: Code Quality
23
on: [push, pull_request]
34

5+
permissions: read-all
6+
47
jobs:
58
lint:
69
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
712
steps:
8-
- uses: actions/checkout@v6
9-
13+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
14+
1015
- name: Check file permissions
1116
run: |
1217
find . -type f -perm /111 -name "*.sh" | head -10 || true
13-
18+
1419
- name: Check for secrets
15-
uses: trufflesecurity/trufflehog@main
20+
uses: trufflesecurity/trufflehog@8a2639a09a43832dcde73f78f7c9eb8cfe498ec0 # v3.88.26
1621
with:
1722
path: ./
1823
base: ${{ github.event.pull_request.base.sha || github.event.before }}
1924
head: ${{ github.sha }}
2025
continue-on-error: true
21-
26+
2227
- name: Check TODO/FIXME
2328
run: |
2429
echo "=== TODOs ==="
2530
grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.rs" --include="*.res" --include="*.py" --include="*.ex" . | head -20 || echo "None found"
26-
31+
2732
- name: Check for large files
2833
run: |
2934
find . -type f -size +1M -not -path "./.git/*" | head -10 || echo "No large files"
30-
35+
3136
- name: EditorConfig check
32-
uses: editorconfig-checker/action-editorconfig-checker@main
37+
uses: editorconfig-checker/action-editorconfig-checker@64a66abd86fb07d9a6f0ddc46b4d6a8bf51f3a4e # v2.0.0
3338
continue-on-error: true
3439

3540
docs:
3641
runs-on: ubuntu-latest
42+
permissions:
43+
contents: read
3744
steps:
38-
- uses: actions/checkout@v6
45+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
3946
- name: Check documentation
4047
run: |
4148
MISSING=""
4249
[ ! -f "README.md" ] && [ ! -f "README.adoc" ] && MISSING="$MISSING README"
4350
[ ! -f "LICENSE" ] && [ ! -f "LICENSE.txt" ] && [ ! -f "LICENSE.md" ] && MISSING="$MISSING LICENSE"
4451
[ ! -f "CONTRIBUTING.md" ] && [ ! -f "CONTRIBUTING.adoc" ] && MISSING="$MISSING CONTRIBUTING"
45-
52+
4653
if [ -n "$MISSING" ]; then
4754
echo "::warning::Missing docs:$MISSING"
4855
else

.github/workflows/rsr-antipattern.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# RSR Anti-Pattern CI Check
21
# SPDX-License-Identifier: AGPL-3.0-or-later
2+
# RSR Anti-Pattern CI Check
33
#
44
# Enforces: No TypeScript, No Go, No Python (except SaltStack), No npm
55
# Allows: ReScript, Deno, WASM, Rust, OCaml, Haskell, Guile/Scheme
@@ -12,11 +12,15 @@ on:
1212
pull_request:
1313
branches: [main, master, develop]
1414

15+
permissions: read-all
16+
1517
jobs:
1618
antipattern-check:
1719
runs-on: ubuntu-latest
20+
permissions:
21+
contents: read
1822
steps:
19-
- uses: actions/checkout@v6
23+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
2024

2125
- name: Check for TypeScript
2226
run: |

.github/workflows/scorecard.yml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
12
name: OSSF Scorecard
23
on:
34
push:
@@ -14,17 +15,17 @@ jobs:
1415
security-events: write
1516
id-token: write
1617
steps:
17-
- uses: actions/checkout@v6
18+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
1819
with:
1920
persist-credentials: false
20-
21+
2122
- name: Run Scorecard
22-
uses: ossf/scorecard-action@v2.4.3
23+
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
2324
with:
2425
results_file: results.sarif
2526
results_format: sarif
26-
27+
2728
- name: Upload results
28-
uses: github/codeql-action/upload-sarif@v4
29+
uses: github/codeql-action/upload-sarif@45c3735bb49d9db0f52accd65a74a86f6a0da4b6 # v3.31.9
2930
with:
3031
sarif_file: results.sarif
Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,43 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
12
name: Security Policy
23
on: [push, pull_request]
4+
5+
permissions: read-all
6+
37
jobs:
48
check:
59
runs-on: ubuntu-latest
10+
permissions:
11+
contents: read
612
steps:
7-
- uses: actions/checkout@v6
13+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
814
- name: Security checks
915
run: |
1016
FAILED=false
11-
17+
1218
# Block MD5/SHA1 for security (allow for checksums/caching)
1319
WEAK_CRYPTO=$(grep -rE 'md5\(|sha1\(' --include="*.py" --include="*.rb" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" . 2>/dev/null | grep -v 'checksum\|cache\|test\|spec' | head -5 || true)
1420
if [ -n "$WEAK_CRYPTO" ]; then
1521
echo "⚠️ Weak crypto (MD5/SHA1) detected. Use SHA256+ for security:"
1622
echo "$WEAK_CRYPTO"
1723
fi
18-
24+
1925
# Block HTTP URLs (except localhost)
2026
HTTP_URLS=$(grep -rE 'http://[^l][^o][^c]' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.yaml" --include="*.yml" . 2>/dev/null | grep -v 'localhost\|127.0.0.1\|example\|test\|spec' | head -5 || true)
2127
if [ -n "$HTTP_URLS" ]; then
2228
echo "⚠️ HTTP URLs found. Use HTTPS:"
2329
echo "$HTTP_URLS"
2430
fi
25-
31+
2632
# Block hardcoded secrets patterns
2733
SECRETS=$(grep -rEi '(api_key|apikey|secret_key|password)\s*[=:]\s*["\x27][A-Za-z0-9+/=]{20,}' --include="*.py" --include="*.js" --include="*.ts" --include="*.go" --include="*.rs" --include="*.env" . 2>/dev/null | grep -v 'example\|sample\|test\|mock\|placeholder' | head -3 || true)
2834
if [ -n "$SECRETS" ]; then
2935
echo "❌ Potential hardcoded secrets detected!"
3036
FAILED=true
3137
fi
32-
38+
3339
if [ "$FAILED" = true ]; then
3440
exit 1
3541
fi
36-
42+
3743
echo "✅ Security policy check passed"

.github/workflows/wellknown-enforcement.yml

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# SPDX-License-Identifier: AGPL-3.0-or-later
12
name: Well-Known Standards (RFC 9116 + RSR)
23
on:
34
push:
@@ -13,32 +14,36 @@ on:
1314
- cron: '0 9 * * 1'
1415
workflow_dispatch:
1516

17+
permissions: read-all
18+
1619
jobs:
1720
validate:
1821
runs-on: ubuntu-latest
22+
permissions:
23+
contents: read
1924
steps:
20-
- uses: actions/checkout@v6
21-
25+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
26+
2227
- name: RFC 9116 security.txt validation
2328
run: |
2429
SECTXT=""
2530
[ -f ".well-known/security.txt" ] && SECTXT=".well-known/security.txt"
2631
[ -f "security.txt" ] && SECTXT="security.txt"
27-
32+
2833
if [ -z "$SECTXT" ]; then
2934
echo "::warning::No security.txt found. See https://github.com/hyperpolymath/well-known-ecosystem"
3035
exit 0
3136
fi
32-
37+
3338
# Required: Contact
3439
grep -q "^Contact:" "$SECTXT" || { echo "::error::Missing Contact field"; exit 1; }
35-
40+
3641
# Required: Expires
3742
if ! grep -q "^Expires:" "$SECTXT"; then
3843
echo "::error::Missing Expires field"
3944
exit 1
4045
fi
41-
46+
4247
# Check expiry
4348
EXPIRES=$(grep "^Expires:" "$SECTXT" | cut -d: -f2- | tr -d ' ' | head -1)
4449
if date -d "$EXPIRES" > /dev/null 2>&1; then
@@ -59,7 +64,7 @@ jobs:
5964
[ ! -f ".well-known/security.txt" ] && [ ! -f "security.txt" ] && MISSING="$MISSING security.txt"
6065
[ ! -f ".well-known/ai.txt" ] && MISSING="$MISSING ai.txt"
6166
[ ! -f ".well-known/humans.txt" ] && MISSING="$MISSING humans.txt"
62-
67+
6368
if [ -n "$MISSING" ]; then
6469
echo "::warning::Missing RSR recommended files:$MISSING"
6570
echo "Reference: https://github.com/hyperpolymath/well-known-ecosystem/.well-known/"

0 commit comments

Comments
 (0)