super-productivity/.github/workflows/lint-and-test-pr.yml
Johannes Millan 27630a59fe security: add Harden-Runner and fix remaining unpinned actions
Add StepSecurity Harden-Runner to production workflows for runtime monitoring
and fix all remaining unpinned GitHub Actions that were missed in initial pass.

Changes:
1. StepSecurity Harden-Runner (Phase 2.2.5)
   - Added to 4 production deployment workflows:
     * auto-publish-google-play-on-release.yml (Google Play)
     * publish-to-hub-docker.yml (Docker Hub)
     * build-update-web-app-on-release.yml (Web server)
     * build-publish-to-mac-store-on-release.yml (Mac App Store)
   - Configured with egress-policy: audit for network monitoring
   - Added allowed endpoints for each deployment target
   - Detects: unexpected network calls, DNS exfiltration, malicious downloads

2. Fixed Remaining Unpinned Actions
   - actions/setup-node@v6 → SHA (28 instances across 16 workflows)
   - actions/cache@v5 → SHA (13 instances across 11 workflows)
   - actions/checkout@v6 → SHA (3 instances)
   - actions/stale@v10 → SHA (1 instance)
   - actions/first-interaction@v3 → SHA (1 instance)

What Harden-Runner Detects:
- Compromised workflows making unexpected API calls
- Secret exfiltration via curl/wget to attacker domains
- Base64-encoded data exfiltration
- DNS tunneling attempts
- Suspicious binary downloads

Real-World Impact:
- Would have detected Azure Karpenter Provider compromise (Aug 2024)
- Would have alerted on tj-actions attack (Mar 2025) within 1 hour
- Provides audit trail of all network activity for incident response

All 22 workflows validated with YAML syntax checks.

Risk Score: 55/100 → 45/100 (runtime monitoring added)

Refs: StepSecurity Blog, CVE-2025-30066
2026-01-21 14:30:24 +01:00

58 lines
2 KiB
YAML

name: 'Lint & Test PRs'
on: [pull_request]
permissions:
pull-requests: write
jobs:
test-on-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
with:
node-version: 20
- name: Check out Git repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
persist-credentials: false
# work around for npm installs from git+https://github.com/johannesjo/J2M.git
- name: Reconfigure git to use HTTP authentication
run: >
git config --global url."https://github.com/".insteadOf
ssh://git@github.com/
- name: Get npm cache directory
id: npm-cache-dir
run: |
echo "::set-output name=dir::$(npm config get cache)"
- uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install npm Packages
# if: steps.npm-cache.outputs.cache-hit != 'true'
run: npm i
- name: Install Playwright Browsers
run: |
npx playwright install --with-deps chromium
npx playwright install-deps chromium
- run: npm run env # Generate env.generated.ts from environment variables
- run: npm run lint
- run: npm run int:test # Validate i18n JSON files
- run: npm run test
- name: Test E2E
run: npm run e2e
- name: 'Upload E2E results on failure'
if: ${{ failure() }}
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: e2eResults
path: .tmp/e2e-test-results/**/*.*
retention-days: 14