ci: harden email-guard — scan message trailers + run on push #1
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: Email Guard | |
| # Privacy guard: every commit's author AND committer must be the maintainer's GitHub | |
| # no-reply, and no commit message may carry a personal-provider email (e.g. a | |
| # `Co-authored-by:` trailer). Runs on pull requests AND on direct pushes to main. | |
| # Make the "Commit email privacy" check a required status check on main. | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| jobs: | |
| email-guard: | |
| name: Commit email privacy | |
| runs-on: ubuntu-latest | |
| env: | |
| # Exact account only ("only my account"): | |
| ALLOWED_EMAIL_PATTERN: '^32437578\+bntvllnt@users\.noreply\.github\.com$' | |
| # Personal mail providers that must never appear in a commit message/trailer: | |
| PERSONAL_PROVIDER_RE: '@(icloud|gmail|googlemail|hotmail|outlook|live|yahoo|ymail|proton|protonmail|aol|gmx|zoho|fastmail)\.' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Scan commit identities + message trailers for leaked emails | |
| run: | | |
| set -euo pipefail | |
| # On a pull_request build, HEAD is GitHub's synthetic merge commit; the | |
| # base..head range checks just the pushed commits. On push, before..sha. | |
| if [ "${{ github.event_name }}" = "pull_request" ]; then | |
| LOGARGS='${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}' | |
| else | |
| BEFORE='${{ github.event.before }}' | |
| if [ -n "$BEFORE" ] && [ "$BEFORE" != "0000000000000000000000000000000000000000" ] && git rev-parse -q --verify "$BEFORE^{commit}" >/dev/null 2>&1; then | |
| LOGARGS="$BEFORE..${{ github.sha }}" | |
| else | |
| LOGARGS="-1 ${{ github.sha }}" | |
| fi | |
| fi | |
| echo "Scanning: git log $LOGARGS" | |
| fail=0 | |
| # 1) author + committer must be the owner no-reply | |
| ids=$(git log --format='%ae%n%ce' $LOGARGS | sort -u | grep -v '^$' || true) | |
| echo "Identities:"; echo "$ids" | sed 's/^/ /' | |
| while IFS= read -r e; do | |
| [ -z "$e" ] && continue | |
| if ! printf '%s' "$e" | grep -qE "$ALLOWED_EMAIL_PATTERN"; then | |
| echo "::error::Disallowed author/committer email: $e (use your GitHub no-reply)"; fail=1 | |
| fi | |
| done <<< "$ids" | |
| # 2) no personal-provider email anywhere in the message bodies (e.g. Co-authored-by) | |
| msgmails=$(git log --format='%B' $LOGARGS | grep -aoiE '[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}' | sort -u || true) | |
| while IFS= read -r e; do | |
| [ -z "$e" ] && continue | |
| if printf '%s' "$e" | grep -qiE "$PERSONAL_PROVIDER_RE"; then | |
| echo "::error::Personal email in a commit message/trailer: $e (strip Co-authored-by trailers)"; fail=1 | |
| fi | |
| done <<< "$msgmails" | |
| if [ "$fail" -ne 0 ]; then exit 1; fi | |
| echo "OK — commit identities are the no-reply and no personal emails in messages." |