Files
Alex Jbanca 32737dcdd6 ci: pin status-go submodule URL to upstream in PR checks
A PR can edit .gitmodules to point vendor/status-go at an arbitrary
remote, letting the policy check validate against attacker-controlled
refs (a fake develop branch containing any pin). Override the configured
URL with the canonical upstream before 'git submodule update' in both
jobs; a pin that doesn't exist upstream now fails the update, which is
the correct verdict.
2026-07-28 14:50:54 +03:00

138 lines
5.9 KiB
YAML

name: PR Checks
on:
pull_request:
branches:
- master
- release/**
types:
- opened
- synchronize
- reopened
- edited
jobs:
check-status-go-submodule:
name: Check status-go submodule branch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# head SHA, not head_ref: fork branches don't exist in this repo,
# but their commits are fetchable by SHA via the PR ref network
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
submodules: false
- name: Get status-go submodule commit
id: statusgo
run: |
commit=$(git ls-tree HEAD vendor/status-go | awk '{print $3}')
echo "commit=$commit" >> $GITHUB_OUTPUT
echo "[LOG] status-go submodule commit: $commit"
- name: Fetch relevant status-go branches
run: |
# pin the submodule URL so a PR-modified .gitmodules cannot point
# the policy check at a non-upstream remote
git submodule init vendor/status-go
git config submodule.vendor/status-go.url https://github.com/status-im/status-go.git
git submodule update vendor/status-go
cd vendor/status-go
if ! git fetch origin 'release/*:refs/remotes/origin/release/*' 2>/dev/null; then
echo "[WARN] No release/* branches found."
fi
if ! git fetch origin develop:refs/remotes/origin/develop 2>/dev/null; then
echo "[WARN] develop branch not found on remote."
fi
echo "[LOG] status-go relevant branches fetched."
- name: Get containing branches
id: branches
run: |
cd vendor/status-go
branches=$(git branch -r --contains ${{ steps.statusgo.outputs.commit }} | sed 's/ *origin\///')
# Normalize branch list: remove 'HEAD -> ...', trim whitespace, one per line
cleaned_branches=$(echo "$branches" | sed '/HEAD ->/d' | awk '{$1=$1};1')
echo "branches<<EOF" >> $GITHUB_OUTPUT
echo "$cleaned_branches" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
echo "[LOG] status-go commit is contained in branches:"
echo "$cleaned_branches"
- name: Fetch base branch status-go commit
run: |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }}
BASE_STATUS_GO_COMMIT=$(git ls-tree ${{ github.base_ref }} vendor/status-go | awk '{print $3}')
echo "BASE_STATUS_GO_COMMIT=$BASE_STATUS_GO_COMMIT" >> $GITHUB_ENV
echo "[LOG] status-go commit on base branch (${{ github.base_ref }}): $BASE_STATUS_GO_COMMIT"
- name: Check if status-go submodule changed
id: check_statusgo_changed
run: |
git fetch origin ${{ github.base_ref }}
if git diff --name-only origin/${{ github.base_ref }} HEAD | grep -q '^vendor/status-go$'; then
echo "changed=true" >> $GITHUB_OUTPUT
echo "[LOG] status-go submodule changed in this PR."
else
echo "changed=false" >> $GITHUB_OUTPUT
echo "[LOG] status-go submodule NOT changed in this PR."
fi
- name: Validate status-go branch policy for master
if: steps.check_statusgo_changed.outputs.changed == 'true' && github.base_ref == 'master'
run: |
BRANCHES="${{ steps.branches.outputs.branches }}"
echo "[LOG] Checking branch policy for master branch"
if ! echo "$BRANCHES" | grep -x 'develop'; then
echo "::error::status-go submodule must point to a commit on 'develop' branch when PR targets master."
exit 1
fi
echo "[LOG] status-go commit is on develop branch."
- name: Validate status-go branch policy for release
if: steps.check_statusgo_changed.outputs.changed == 'true' && startsWith(github.base_ref, 'release/')
run: |
BRANCHES="${{ steps.branches.outputs.branches }}"
echo "[LOG] Checking branch policy for release branch: ${{ github.base_ref }}"
if ! echo "$BRANCHES" | grep -E '^release/' >/dev/null; then
echo "::error::status-go submodule must point to a commit on a 'release/*' branch when PR targets a release branch."
exit 1
fi
echo "[LOG] status-go commit is on a release/* branch."
- name: Validate status-go commit recency
if: steps.check_statusgo_changed.outputs.changed == 'true'
run: |
STATUS_GO_COMMIT="${{ steps.statusgo.outputs.commit }}"
BASE_STATUS_GO_COMMIT="$BASE_STATUS_GO_COMMIT"
echo "[LOG] Checking commit recency: PR=$STATUS_GO_COMMIT, base=$BASE_STATUS_GO_COMMIT"
cd vendor/status-go
if git merge-base --is-ancestor "$BASE_STATUS_GO_COMMIT" "$STATUS_GO_COMMIT"; then
echo "[LOG] status-go commit is newer than or equal to base branch. OK."
else
echo "::error::status-go submodule commit in PR is older than the one on the base branch."
exit 1
fi
wakuext-binding-contract:
name: wakuext FFI binding contract
runs-on: ubuntu-latest
steps:
# default (merge) ref on purpose: the contract must hold on the result of
# merging the PR, not on the PR's possibly-stale vendor pin
- uses: actions/checkout@v4
with:
submodules: false
- name: Init vendored status-go (the shipped pin)
run: |
# same URL pinning as above: never fetch a PR-supplied remote
git submodule init vendor/status-go
git config submodule.vendor/status-go.url https://github.com/status-im/status-go.git
git submodule update vendor/status-go
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- run: pip install pytest==8.4.1
- name: Run the binding contract
run: python -m pytest test/contract/test_wakuext_binding.py -v