Repository navigation
Limit beta preflight Lambda output to health and key names (#85) #126
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security baseline | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| schedule: | |
| # Monday 03:31 JST. The non-round minute avoids peak scheduler load. | |
| - cron: '31 18 * * 0' | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: security-baseline-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| secret-scan: | |
| name: Full-history secret scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out full history | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Check public repository boundary | |
| run: python3 scripts/check_public_repo.py --tracked | |
| # It only ran in pre-commit, so a clone without the hook installed, or a | |
| # change made through the web UI, went straight through (noticed | |
| # 2026-09-03). Run it over every tracked text file. The checker itself is | |
| # excluded via .langcheckignore, because it holds the characters it looks | |
| # for in its own regexes. | |
| - name: Check language contamination | |
| run: | | |
| git ls-files '*.md' '*.mjs' '*.js' '*.ts' '*.html' '*.py' \ | |
| | xargs python3 scripts/check_language_contamination.py | |
| # gitleaks-action is not used here: it decides the scan range itself. | |
| # | |
| # Measured 2026-09-17: this job was named "Full-history secret scan" and | |
| # checked out with fetch-depth: 0, but the action adds | |
| # --log-opts=--no-merges --first-parent <sha>^..<sha>, so on pull_request | |
| # and push it scanned a single commit (149-5,675 bytes). | |
| # | |
| # Correction (same day): an earlier version of this comment claimed the full | |
| # history was never scanned and that past secrets could never be found. That | |
| # was wrong. The action only narrows the range on push and pull_request; on | |
| # schedule it passes no --log-opts and scans the whole history (measured: | |
| # 183 commits / 1.63 MB). The real problems are that the job name did not | |
| # match what it did per PR, and that a change merged in a PR was not looked | |
| # at from a full-history angle until that week's cron run. | |
| # | |
| # gitleaks is called directly so the range is explicit. The version is | |
| # pinned and the download is verified with SHA-256. | |
| - name: Install gitleaks (pinned + checksum verified) | |
| env: | |
| GITLEAKS_VERSION: 8.30.1 | |
| GITLEAKS_SHA256: 551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb | |
| run: | | |
| set -euo pipefail | |
| curl -sSfL -o /tmp/gitleaks.tar.gz \ | |
| "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" | |
| echo "${GITLEAKS_SHA256} /tmp/gitleaks.tar.gz" | sha256sum -c - | |
| tar -xzf /tmp/gitleaks.tar.gz -C /tmp gitleaks | |
| /tmp/gitleaks version | |
| - name: Scan the whole history | |
| run: | | |
| set -euo pipefail | |
| # No --log-opts: gitleaks walks the whole history by default. | |
| /tmp/gitleaks git . --redact -v --exit-code 1 \ | |
| --report-format sarif --report-path gitleaks.sarif 2>&1 | tee gitleaks.log | |
| # A green check is not evidence that anything was looked at. Read the number | |
| # of commits gitleaks reported and fail if it does not match the repository's | |
| # history. Measured range across 10 VEAI repos (2026-09-17): 82-181% of HEAD. | |
| # The broken state was 0.45% (1 of 222), so a 50% floor catches it. | |
| - name: Verify the scan actually covered the history | |
| if: always() | |
| run: | | |
| set -euo pipefail | |
| expected=$(git rev-list --count HEAD) | |
| scanned=$(grep -oE '[0-9]+ commits scanned' gitleaks.log | grep -oE '^[0-9]+' | head -1 || echo 0) | |
| floor=$(( expected / 2 )) | |
| [ "$floor" -lt 2 ] && floor=2 | |
| echo "history=${expected} scanned=${scanned} floor=${floor}" | |
| if [ "$scanned" -lt "$floor" ]; then | |
| echo "::error::Did not scan the whole history (${scanned} of ${expected} commits). The job is not doing what its name says." | |
| exit 1 | |
| fi | |
| echo "Scanned the whole history (${scanned} commits)." | |
| dependency-audit: | |
| name: Node.js dependency audit | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 | |
| - name: Set up Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 | |
| with: | |
| node-version: 24 | |
| cache: npm | |
| - name: Audit dependencies | |
| run: npm audit --audit-level=high |