From 3c25de17cb120a7b0ac22d1fa88edbc59e56933e Mon Sep 17 00:00:00 2001 From: Andrii Pasternak Date: Wed, 13 May 2026 00:37:09 +0100 Subject: [PATCH] ci(security): SHA-pin third-party actions, move dev host to secrets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit deploy-dev.yml referenced tailscale/github-action@v2 and appleboy/ssh-action@v1 — both unpinned third-party actions handling TAILSCALE_AUTH_KEY (tailnet join) and DEV_SSH_KEY (sudo SSH on dev host). A single supply-chain hijack (account takeover, malicious forced retag) exfils both credentials on the next push to dev. SHA-pinned to mitigate. Same workflow hardcoded the dev Tailscale CGNAT IP and SSH username in a PUBLIC repo, leaking the dev host's tailnet topology. Moved both to GitHub repo secrets (DEV_HOST, DEV_USER) — must be set before merge or the next deploy fails fast. CLAUDE.md forbids internal addresses in this public tree. While here, SHA-pinned the other two workflows with third-party actions (pypa/gh-action-pypi-publish, google-github-actions/*) for defense in depth. First-party actions/* keep their major-tag pins per GitHub's documented recommendation (GitHub itself signs and re-tags those). After-state: zero unpinned third-party uses: lines across .github/workflows/. --- .github/workflows/deploy-dev.yml | 12 ++++++++---- .github/workflows/publish-cli.yml | 3 ++- .github/workflows/sync-docs-to-vertex.yml | 6 ++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 1418b09b0..a822ad8a8 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -11,15 +11,19 @@ jobs: steps: - name: Connect to Tailscale - uses: tailscale/github-action@v2 + # SHA-pinned to mitigate supply-chain hijack of the v2 floating tag. + uses: tailscale/github-action@05c58255396c88c609919d571a8b117099c69020 # v2 with: authkey: ${{ secrets.TAILSCALE_AUTH_KEY }} - name: Deploy - uses: appleboy/ssh-action@v1 + # SHA-pinned to mitigate supply-chain hijack of the v1 floating tag. + uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1 with: - host: 100.96.144.19 - username: trinity + # Host + username come from repo secrets so this public workflow file + # doesn't disclose the Tailscale topology of the dev environment. + host: ${{ secrets.DEV_HOST }} + username: ${{ secrets.DEV_USER }} key: ${{ secrets.DEV_SSH_KEY }} command_timeout: 25m script: | diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml index 52adfa178..ea5f0da63 100644 --- a/.github/workflows/publish-cli.yml +++ b/.github/workflows/publish-cli.yml @@ -84,7 +84,8 @@ jobs: - name: Publish to PyPI if: steps.check.outputs.skip != 'true' - uses: pypa/gh-action-pypi-publish@release/v1 + # SHA-pinned to mitigate supply-chain hijack of the release/v1 branch. + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1 with: packages-dir: src/cli/dist/ diff --git a/.github/workflows/sync-docs-to-vertex.yml b/.github/workflows/sync-docs-to-vertex.yml index e41cd6ebd..8c409ef70 100644 --- a/.github/workflows/sync-docs-to-vertex.yml +++ b/.github/workflows/sync-docs-to-vertex.yml @@ -26,13 +26,15 @@ jobs: uses: actions/checkout@v4 - name: Authenticate to Google Cloud - uses: google-github-actions/auth@v2 + # SHA-pinned to mitigate supply-chain hijack of the v2 floating tag. + uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2 with: workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }} - name: Set up Cloud SDK - uses: google-github-actions/setup-gcloud@v2 + # SHA-pinned to mitigate supply-chain hijack of the v2 floating tag. + uses: google-github-actions/setup-gcloud@e427ad8a34f8676edf47cf7d7925499adf3eb74f # v2 - name: Convert and sync docs to GCS run: |