Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .github/workflows/claude-wif-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ jobs:
github.event.comment.author_association == 'OWNER')
runs-on: arc-runner-set
timeout-minutes: 10
env:
HOME: /tmp
steps:
- name: Get PR ref
if: github.event_name == 'issue_comment'
Expand All @@ -36,18 +38,18 @@ jobs:
repository: ${{ steps.pr.outputs.repo || github.repository }}
persist-credentials: false

- name: Install Claude Code
run: |
curl -fsSL https://claude.ai/install.sh | bash
echo "$HOME/.local/bin" >> $GITHUB_PATH

- name: Authenticate to GCP via WIF
uses: google-github-actions/auth@c200f3691d83b41bf9bbd8638997a462592937ed # v2
with:
project_id: hosted-control-planes
service_account: claude-gha@hosted-control-planes.iam.gserviceaccount.com
workload_identity_provider: projects/21066242673/locations/global/workloadIdentityPools/itpc-identity-pool/providers/github.com

- name: Install Claude Code
run: |
curl -fsSL https://claude.ai/install.sh | bash
echo "$HOME/.local/bin" >> $GITHUB_PATH
Comment on lines +48 to +51

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if claude.ai provides checksums or signatures for the installer

curl -fsSL -I https://claude.ai/install.sh
curl -fsSL https://claude.ai/install.sh.sha256 || echo "No SHA256 checksum found"
curl -fsSL https://claude.ai/install.sh.sig || echo "No signature found"

Repository: openshift/hypershift

Length of output: 1745


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and print the relevant portion of the workflow to understand credential context
path=".github/workflows/claude-wif-test.yaml"
if [ ! -f "$path" ]; then
  echo "Missing file: $path"
  exit 1
fi

echo "== file: $path (lines around 1-120) =="
nl -ba "$path" | sed -n '1,140p'

echo "== grep for auth/WIF/credentials in workflow =="
rg -n "wif|workload identity|credentials|gcp|google|service account|id-token|permissions|actions/checkout|setup-.*gcloud|workloadIdentity" "$path" || true

echo "== grep for the install step =="
rg -n "Install Claude Code|install\.sh|claude\.ai/install\.sh|GITHUB_PATH|\.local/bin" "$path" || true

Repository: openshift/hypershift

Length of output: 198


🏁 Script executed:

#!/bin/bash
set -euo pipefail

path=".github/workflows/claude-wif-test.yaml"
echo "== checking file exists: $path =="
ls -la "$path"

echo "== file header (lines 1-120) =="
cat -n "$path" | sed -n '1,140p'

echo "== grep for WIF/credentials/auth context =="
rg -n "wif|workload identity|credentials|gcp|google|service account|id-token|setup-gcloud|workloadIdentity|GCP" "$path" || true

echo "== grep for install step bits =="
rg -n "Install Claude Code|install\.sh|claude\.ai/install\.sh|downloads\.claude\.ai|curl|bash|GITHUB_PATH|\.local/bin" "$path" || true

echo "== follow redirect and check checksum/signature endpoints =="
redir="$(curl -fsSL -I https://claude.ai/install.sh 2>/dev/null | awk -F': ' '/^location: /{print $2}' | tr -d '\r')"
echo "redirect location: ${redir:-<none>}"

# If we got a redirect, try likely checksum/signature URL patterns for the actual script.
if [ -n "${redir:-}" ]; then
  base="${redir%/*}"
  file="${redir##*/}"

  # Try same patterns used in the review comment, relative to the redirect target.
  curl -fsSL -I "${base}/${file}.sha256" >/dev/null && echo "FOUND sha256 at ${base}/${file}.sha256" || echo "No SHA256 checksum at ${base}/${file}.sha256"
  curl -fsSL -I "${base}/${file}.sig" >/dev/null && echo "FOUND sig at ${base}/${file}.sig" || echo "No signature at ${base}/${file}.sig"
fi

Repository: openshift/hypershift

Length of output: 3939


🏁 Script executed:

#!/bin/bash
set -euo pipefail

url="https://downloads.claude.ai/claude-code-releases/bootstrap.sh"
tmp="/tmp/claude-bootstrap.sh"

echo "== fetching $url to $tmp (no execute) =="
curl -fsSL "$url" -o "$tmp"

echo "== size/first 60 lines =="
wc -l "$tmp"
head -n 60 "$tmp" | sed -e 's/\t/    /g'

echo "== searching for verification-related strings =="
rg -n "sha256|sha1|md5|gpg|gpgv|pgp|cosign|sig|signature|verify|verification|openssl dgst|shasum|checksum|integrity|public key|keyring" "$tmp" || true

echo "== searching for download/extract/execution flow =="
rg -n "curl|wget|tar|unzip|sh -c|bash|chmod \\+x|./|exec " "$tmp" | head -n 80 || true

echo "== last 60 lines =="
tail -n 60 "$tmp" | sed -e 's/\t/    /g'

Repository: openshift/hypershift

Length of output: 6207


Supply chain risk: unverified installer script executed after WIF auth

The workflow runs curl -fsSL https://claude.ai/install.sh | bash after the “Authenticate to GCP via WIF” step. Even though the redirected bootstrap.sh script verifies the SHA256 of the downloaded claude binary against a manifest checksum, the bootstrap script itself is executed without any hash/signature validation or version pinning, and it installs the latest release at runtime. If claude.ai/downloads.claude.ai is tampered with, arbitrary code could run with the job’s WIF-enabled permissions.

Mitigations:

  • Fetch the bootstrap script to a file and verify it (hash/signature) before executing (or vendor it and pin).
  • Pin the installer to a specific Claude Code version/manifest instead of using latest.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/claude-wif-test.yaml around lines 48 - 51, Replace the
unsafe piped installer invocation "curl -fsSL https://claude.ai/install.sh |
bash" with a two-step verified install: download the bootstrap script to a file
(e.g., via curl), verify its integrity/signature against a pinned hash or
signature from a trusted source (or vendor the bootstrap script into the repo),
and only then execute it; also ensure the bootstrap is instructed to install a
pinned Claude Code release/manifest (not latest) or fetch a pinned manifest and
verify the downloaded binary checksum before installation. Locate the workflow
step that runs the installer (the run block containing the curl | bash line) and
update it to perform explicit download, verification, and pinned-version
installation instead of executing the remote script directly.


- name: Test Claude Code
env:
CLAUDE_CODE_USE_VERTEX: "1"
Expand Down