Skip to content

chore(release): v0.31.0 (M4 API/format freeze) (#156) #386

chore(release): v0.31.0 (M4 API/format freeze) (#156)

chore(release): v0.31.0 (M4 API/format freeze) (#156) #386

Workflow file for this run

name: Security scan
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
schedule:
# Weekly Monday 06:00 UTC catches new CVEs in dependencies and
# any drift in the scan rules.
- cron: "0 6 * * 1"
permissions:
contents: read
jobs:
secrets:
name: Secret scan (gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Install gitleaks
run: |
GITLEAKS_VERSION="8.21.0"
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
-o /tmp/gitleaks.tgz
tar -xzf /tmp/gitleaks.tgz -C /tmp gitleaks
sudo install -m 0755 /tmp/gitleaks /usr/local/bin/gitleaks
- name: Run gitleaks
run: gitleaks detect --no-banner --redact --verbose
planning-leak:
name: Planning-doc identifier leak
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Scan for internal identifiers
shell: bash
run: |
set -uo pipefail
# Identifier patterns belonging to the private planning repo
# that must never appear in public tracked files:
# Y-N (Y-1, Y-2, Y-3a, Y-7b)
# Y-N.N (Y-1.5)
# B-XN (B-D1, B-D2)
# "Codex YN" review references
# M-N (M-1 cross-product playbook, M-2 dispute appeal)
# The literal private-repo name
# The workflow file itself is excluded from the scan because
# the documented examples and regex literal above would
# otherwise self-match.
MATCHES=$(git ls-files | grep -v '^\.github/workflows/' | xargs grep -nE \
"Y-[0-9]+[a-z]?|Y-[0-9]+\.[0-9]+|B-[A-Z][0-9]+|Codex Y[0-9]+|M-[0-9]+[a-z]?|basou-planning" \
2>/dev/null || true)
if [ -n "$MATCHES" ]; then
echo "::error::Planning-doc identifier leak detected"
echo "$MATCHES"
exit 1
fi
echo "No planning-doc identifier leaks found."
absolute-path:
name: Absolute path leak
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Scan for real /Users/<username> paths
shell: bash
run: |
set -uo pipefail
# Path-sanitizer JSDoc documents these intentional placeholders.
# Anything outside this set is a real absolute-path leak.
ALLOWED='^/Users/(u|<u>|<user>|<you>|example|secret)$'
REAL_PATHS=$(git ls-files | xargs grep -hoE "/Users/[a-zA-Z][a-zA-Z0-9_-]+" 2>/dev/null \
| sort -u | grep -vE "$ALLOWED" || true)
if [ -n "$REAL_PATHS" ]; then
echo "::error::Real /Users/<username> path detected (sanitize to a placeholder)"
echo "$REAL_PATHS"
exit 1
fi
echo "No real absolute-path leaks found."
step-n-watch:
name: Step N cleanup watch (informational)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Count Step N residue
shell: bash
run: |
set -uo pipefail
# Residual "Step N" references in deep source / test comments
# are tracked for follow-up cleanup. They are informational
# only and do not block CI today.
FILES=$(git ls-files | xargs grep -lE "Step [0-9]+" 2>/dev/null || true)
if [ -n "$FILES" ]; then
COUNT=$(echo "$FILES" | wc -l | tr -d ' ')
echo "::warning::${COUNT} file(s) still contain Step N references"
echo "$FILES"
else
echo "No Step N references remain."
fi
commit-message-ascii:
name: Commit message ASCII check
# PR is the only path to main (protect-main ruleset). Push/schedule/
# dispatch events cannot provide a meaningful base..head range, and
# pre-existing non-ASCII commits in history must not be rescanned
# (informational retention, not rewritten). Gating on pull_request
# both prevents new violations and avoids retroactive failures.
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
# Need full history so git log base..head can resolve commits
# between the PR base and head; the default depth=1 would fail.
fetch-depth: 0
- name: Scan new commits for non-ASCII bytes
shell: bash
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -uo pipefail
# CONTRIBUTING.md "English-only convention" requires commit
# messages (subject + body) to be ASCII. The strict range is
# 0x00-0x7F; tab and newline are inside that range and remain
# allowed (the negated class below preserves them).
# Merge commits are excluded: their auto-generated subjects
# are ASCII by construction and merge bodies are not author-
# written content.
# perl is preinstalled on ubuntu-latest and macOS, so the same
# check can be dry-run locally (BSD grep on macOS lacks -P).
FAIL=0
while IFS= read -r -d '' SHA; do
MSG=$(git log -1 --format=%B "$SHA")
SUBJECT=$(git log -1 --format=%s "$SHA")
HITS=$(printf '%s\n' "$MSG" | LC_ALL=C perl -ne 'print "$.:$_" if /[^\x00-\x7F]/')
if [ -n "$HITS" ]; then
FAIL=1
echo "::error::Non-ASCII bytes in commit ${SHA}: ${SUBJECT}"
echo "$HITS" | sed 's/^/ /'
fi
done < <(git log --no-merges -z --format=%H "${BASE_SHA}..${HEAD_SHA}")
if [ "$FAIL" -ne 0 ]; then
echo "::error::One or more new commits contain non-ASCII bytes. See CONTRIBUTING.md 'English-only convention'."
exit 1
fi
echo "All new commits are ASCII-only."
audit:
name: Dependency vulnerability audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v6
# pnpm version is read from the `packageManager` field of the
# workspace root package.json; the action errors out if both
# are specified.
- uses: actions/setup-node@v6
with:
node-version: "20"
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Run pnpm audit (production deps only)
# devDependencies (vitest, biome, tsup, etc.) only run on a
# developer's machine and are not part of the published
# tarball, so vulnerabilities there are not a runtime risk to
# consumers. Track dev-dep advisories via Dependabot if
# needed; here we gate on production-graph vulnerabilities.
run: pnpm audit --audit-level=moderate --prod