ci: serialize Crossplane validation - #22
Conversation
📝 WalkthroughWalkthroughThis PR migrates the validation pipeline from an external reusable Crossplane workflow to an inline, locally-managed Bash script. The Makefile gains a ChangesCI Validation Pipeline Migration
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with 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.
Inline comments:
In @.github/workflows/on-pr.yaml:
- Around line 34-35: Update the workflow to pin mutable GitHub Action refs to
exact commit SHAs for actions/checkout, actions/cache, docker/login-action, and
upbound/action-up-project (replace v6/v5/v3.7.0/v1.1.2 with their corresponding
commit SHAs) and set persist-credentials: false on the actions/checkout step to
prevent the workflow token from being left in the checked-out repo; also replace
the unpinned Crossplane CLI install (the curl | sh command referencing
crossplane/crossplane@master) with a pinned commit SHA or use an official
release artifact/verified installer so the executed script is tied to a specific
commit.
- Around line 58-62: The workflow step "Install Crossplane CLI" currently pipes
the mutable installer at .../master/install.sh into sh; instead download the
installer to a file and execute that saved file, and pin the installer URL to an
immutable commit SHA instead of master. Replace the curl | sh usage by using
curl --fail --location --retry (or similar) to fetch the installer to a local
file (e.g., install.sh), make it executable, and run it with XP_VERSION=v2.0.2
./install.sh; update the URL to point to the specific commit SHA for the
installer script in the crossplane repo to ensure reproducibility.
In @.github/workflows/on-push-main.yaml:
- Around line 54-57: The "Install Crossplane CLI" step currently curls the
installer from the moving master branch; update the run command in that step
(and the identical step in the other workflow) to fetch the installer from a
pinned tag or commit URL (e.g., replace .../master/install.sh with the specific
release tag or commit SHA for Crossplane), and optionally add a checksum or
signature verification step after download before piping to sh to ensure
provenance.
- Around line 30-31: Update the checkout step and third-party action pins to
harden credentials and reduce supply-chain risk: for the Checkout step
(actions/checkout@v6) add persist-credentials: false to prevent token
persistence, and replace the tag pins for actions/checkout, actions/cache@v5,
docker/login-action@v3.7.0, and upbound/action-up-project@v1.1.2 with their
corresponding immutable commit SHAs (pin each action to a specific rev) while
preserving existing inputs and behavior.
In `@scripts/ci-validate-all.sh`:
- Around line 108-118: The render step in render_with_retry captures $? after
the entire if compound which can grab the wrong exit code; move the capture of
the render command's exit status (status=$?) into the else branch immediately
after the failed "up composition render \"$@\" >\"$output\"" so you record the
render exit code instead of the if's exit code, then proceed to rm -f "$output"
and the existing retry/return logic using that status variable.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6ab16827-4e58-4329-a350-11c4600c682a
📒 Files selected for processing (4)
.github/workflows/on-pr.yaml.github/workflows/on-push-main.yamlMakefilescripts/ci-validate-all.sh
| - name: Checkout | ||
| uses: actions/checkout@v6 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the workflow file
ls -la .github/workflows/on-pr.yaml || true
# Print relevant sections with line numbers
nl -ba .github/workflows/on-pr.yaml | sed -n '1,140p'Repository: hops-ops/aws-crossplane-stack
Length of output: 212
🏁 Script executed:
#!/bin/bash
set -euo pipefail
nl -ba .github/workflows/on-pr.yaml | sed -n '1,160p'Repository: hops-ops/aws-crossplane-stack
Length of output: 116
🏁 Script executed:
#!/bin/bash
set -euo pipefail
nl -ba .github/workflows/on-pr.yaml | sed -n '1,220p'Repository: hops-ops/aws-crossplane-stack
Length of output: 116
🏁 Script executed:
#!/bin/bash
set -euo pipefail
nl -ba .github/workflows/on-pr.yaml | sed -n '1,220p'Repository: hops-ops/aws-crossplane-stack
Length of output: 116
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- on-pr.yaml (lines 1-120) ----"
cat -n .github/workflows/on-pr.yaml | sed -n '1,120p'
echo "---- on-pr.yaml (lines 120-220) ----"
cat -n .github/workflows/on-pr.yaml | sed -n '120,220p' || trueRepository: hops-ops/aws-crossplane-stack
Length of output: 3931
🌐 Web query:
GitHub actions/checkout persist-credentials default value
💡 Result:
The default value for the persist-credentials input in the GitHub actions/checkout action is true [1][2][3]. When this option is enabled, the action configures the authentication token or SSH key with the local git configuration, allowing your workflow scripts to run authenticated git commands [1][4][3]. The action automatically removes these credentials during post-job cleanup [1][4]. To opt out of this behavior, you can explicitly set persist-credentials to false in your workflow file [1][5].
Citations:
- 1: https://github.com/actions/checkout/?tab=readme-ov-file
- 2: actions/checkout@c170eef
- 3: https://github.com/actions/checkout/blob/72f2cec99f417b1a1c5e2e88945068983b7965f9/action.yml
- 4: https://github.com/actions/checkout/tree/v6.0.2?tab=readme-ov-file
- 5: https://github.com/actions/checkout/tree/refs/heads/main
🌐 Web query:
GitHub actions/checkout persist-credentials default value
💡 Result:
The default value of the GitHub Actions checkout step input persist-credentials is true.[1][2] In the actions/checkout action.yml, persist-credentials is defined with default: true.[2] The README also documents that the token/credentials are persisted locally unless you set persist-credentials: false to opt out.[1][3].
Citations:
- 1: https://github.com/actions/checkout/tree/refs/heads/main
- 2: https://github.com/actions/checkout/blob/72f2cec99f417b1a1c5e2e88945068983b7965f9/action.yml
- 3: https://github.com/actions/checkout/?tab=readme-ov-file
🌐 Web query:
GitHub actions/checkout persist-credentials default value
💡 Result:
For GitHub Actions actions/checkout, the input persist-credentials default value is true. [1][2][3] This means that if you don’t set persist-credentials explicitly, the checkout action will configure the token/SSH key in the local git config (enabling authenticated git commands), and the token is removed during post-job cleanup. [2][4][1]
Citations:
- 1: https://github.com/actions/checkout/blob/34e114876b0b11c390a56381ad16ebd13914f8d5/action.yml
- 2: https://github.com/actions/checkout/?tab=readme-ov-file
- 3: https://github.com/actions/checkout/blob/72f2cec99f417b1a1c5e2e88945068983b7965f9/action.yml
- 4: https://github.com/actions/checkout/blob/85e6279cec87321a52edac9c87bce653a07cf6c2/README.md
Pin GitHub Actions to commit SHAs and disable persisted checkout credentials
.github/workflows/on-pr.yamluses mutable action refs (actions/checkout@v6,actions/cache@v5,docker/login-action@v3.7.0,upbound/action-up-project@v1.1.2); pin each to an exact commit SHA (applies to checkout: 35, cache: 38, docker login: 64, build: 71).- Checkout currently leaves
persist-credentialsat its default (true), so the workflow token is configured in git; setpersist-credentials: falseto reduce token exposure since later steps execute code from the checked-out repo. - Crossplane CLI install executes a remote script from
crossplane/crossplane@masterviacurl ... | sh; pin the script to a commit SHA (or use a release artifact) to avoid executing an unpinned source.
Suggested hardening
- name: Checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@<pinned-commit-sha>
+ with:
+ persist-credentials: false
...
- name: Cache crossplane
- uses: actions/cache@v5
+ uses: actions/cache@<pinned-commit-sha>
...
- name: Docker login to GHCR
- uses: docker/login-action@v3.7.0
+ uses: docker/login-action@<pinned-commit-sha>
...
- name: Build with up
- uses: upbound/action-up-project@v1.1.2
+ uses: upbound/action-up-project@<pinned-commit-sha>🧰 Tools
🪛 zizmor (1.25.2)
[warning] 34-35: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 35-35: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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/on-pr.yaml around lines 34 - 35, Update the workflow to
pin mutable GitHub Action refs to exact commit SHAs for actions/checkout,
actions/cache, docker/login-action, and upbound/action-up-project (replace
v6/v5/v3.7.0/v1.1.2 with their corresponding commit SHAs) and set
persist-credentials: false on the actions/checkout step to prevent the workflow
token from being left in the checked-out repo; also replace the unpinned
Crossplane CLI install (the curl | sh command referencing
crossplane/crossplane@master) with a pinned commit SHA or use an official
release artifact/verified installer so the executed script is tied to a specific
commit.
Source: Linters/SAST tools
| - name: Install Crossplane CLI | ||
| run: | | ||
| curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh \ | ||
| | XP_VERSION=v2.0.2 sh | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate and print the referenced workflow section
FILE=".github/workflows/on-pr.yaml"
echo "== File: $FILE =="
if [ -f "$FILE" ]; then
nl -ba "$FILE" | sed -n '40,90p'
else
echo "Missing: $FILE"
exit 1
fi
# Search for crossplane install usage elsewhere in workflows
echo
echo "== Search: crossplane install usage =="
rg -n "crossplane.*install|install\\.sh|XP_VERSION|raw\\.githubusercontent\\.com/crossplane/crossplane" .github/workflows || true
# Search for any other pinned version usage (v2.0.2 etc.) in repo
echo
echo "== Search: XP_VERSION pin =="
rg -n "XP_VERSION|v2\.0\.2|crossplane.*v[0-9]+\.[0-9]+\.[0-9]+" .github/workflows || trueRepository: hops-ops/aws-crossplane-stack
Length of output: 175
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/on-pr.yaml"
echo "== File: $FILE =="
if [ -f "$FILE" ]; then
awk 'NR>=40 && NR<=90 {printf "%d\t%s\n", NR, $0}' "$FILE"
else
echo "Missing: $FILE"
exit 1
fi
echo
echo "== Search: crossplane install usage =="
rg -n "crossplane.*install|install\\.sh|XP_VERSION|raw\\.githubusercontent\\.com/crossplane/crossplane" .github/workflows || true
echo
echo "== Search: XP_VERSION pin =="
rg -n "XP_VERSION|v2\\.0\\.2|crossplane.*v[0-9]+\\.[0-9]+\\.[0-9]+" .github/workflows || trueRepository: hops-ops/aws-crossplane-stack
Length of output: 3131
🌐 Web query:
Crossplane v2.0.2 install.sh raw.githubusercontent.com crossplane/crossplane v2.0.2 install.sh
💡 Result:
To install the Crossplane CLI version v2.0.2, you can use the official Crossplane installation script with an environment variable to specify the version [1][2]. The installation script is located at: https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh Run the following command in your terminal to download and install the v2.0.2 binary: curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | XP_VERSION=v2.0.2 sh After running this command, the script will download the binary, which you can then move to your local path (e.g., /usr/local/bin) to use the crossplane CLI [3][4]. Important Installation Notes: 1. Crossplane CLI vs. Crossplane Control Plane: The install script described above is for the Crossplane CLI (command-line tool) [1][2]. The Crossplane control plane itself is installed into a Kubernetes cluster using Helm [5][6]. 2. Version Compatibility: For versions prior to v2.3.0, the installation script identifies the binary as "crank" and renames it to "crossplane" during the installation process [4][7]. 3. Manual Installation: If you prefer not to use the shell script, you can manually download the binary from the official release repository [1][2]. For v2.0.2, you would look for the binary at https://releases.crossplane.io/stable/v2.0.2/bin/ [1][4].
Citations:
- 1: https://docs.crossplane.io/v2.0/cli/
- 2: https://docs.crossplane.io/v2.2/cli/
- 3: https://github.com/crossplane/crossplane/blob/main/install.sh
- 4: https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh
- 5: https://docs.crossplane.io/v2.0/get-started/install/
- 6: https://docs.crossplane.io/latest/get-started/install/
- 7: https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh
🌐 Web query:
Crossplane CLI install.sh security pin commit recommended curl | sh
💡 Result:
Crossplane’s recommended one-liner to install the Crossplane CLI is: curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | sh [1] Security/pinning notes (based on the install script and docs): 1) The command above downloads whatever install.sh exists at the referenced URL and then executes it, so it is not “pinned” to a specific commit of the script. The script itself supports pinning the CLI version you install, via XP_VERSION and XP_CHANNEL environment variables (these choose which artifact to download) [1][2]. 2) The install.sh script downloads a platform-specific CLI binary using curl with flags that fail on HTTP errors and follow redirects (curl -sfL...). It does not, in the portions shown, include an additional integrity check such as verifying a checksum before executing the result [3]. 3) Crossplane’s docs also provide a manual alternative that avoids running the downloaded shell script: you can download the CLI binary directly from the releases repository for your channel/version [1]. Recommended safer patterns you can use: A) Pin the CLI artifact version (still runs unpinned install.sh): XP_VERSION=v1.20.0 curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | sh [1] B) Pin the install script itself (unpinned CLI artifact risk remains unless you also pin XP_VERSION/XP_CHANNEL): - Prefer using a raw URL that targets a specific crossplane/crossplane commit hash for install.sh, rather than the moving /main/ (or /master/) path. The exact content of install.sh can be verified via the raw file at that commit [4]. C) Avoid executing install.sh (most “no-script” approach): - Manually download the CLI binary from the releases repository for your desired channel/version (docs call out that the release repo names the CLI binary “crank”) [1].
Citations:
- 1: https://docs.crossplane.io/latest/cli/
- 2: https://github.com/crossplane/docs/blob/master/content/v1.20/cli/_index.md
- 3: https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh
- 4: https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh
🌐 Web query:
raw.githubusercontent.com/crossplane/crossplane/v2.0.2/install.sh
💡 Result:
The URL you provided (raw.githubusercontent.com/crossplane/crossplane/v2.0.2/install.sh) is an installation script for the Crossplane CLI binary (not the Crossplane Helm chart / controller itself). The script’s job is to download the appropriate CLI binary for your OS/CPU and place it as a local executable (typically into /usr/local/bin via the post-install instructions). It supports selecting release “channel” and “version” via XP_CHANNEL and XP_VERSION environment variables, and handles “older” versions that used the crank binary/artifacts vs newer versions that use crossplane/crossplane-cli artifacts. Key behaviors (from the script logic visible in the repository’s install.sh): 1) Default environment variables - XP_CHANNEL defaults to “stable”. - XP_VERSION defaults to “current”. - BIN defaults to “crossplane”. [1] 2) OS/architecture detection - The script uses uname -s and uname -m to build the OS and ARCH/OS_ARCH values used in the download URL. [1] 3) Artifact URL construction - It constructs a download URL of the form: https://<url_host>/<XP_CHANNEL>/<XP_VERSION>/<url_dir>/<OS_ARCH>/<url_file> [1] - For “compressed” downloads (COMPRESSED=true) it downloads a tarball (crossplane-cli.tar.gz); otherwise it downloads the binary directly. [1] 4) Compatibility logic for older CLI releases - If XP_VERSION is not “current”, it parses the major/minor version. - For versions earlier than 2.3 (major==2 and minor<3, or major<2), it switches to: - url_host = releases.crossplane.io - bundle_name = crank.tar.gz - BIN = crank Otherwise it uses: - url_host = cli.crossplane.io - bundle_name = crossplane-cli.tar.gz - BIN name “crossplane” [1] 5) Download, unpack, and rename - It downloads with curl -sfL and exits with an error if the requested version/channel artifacts are missing. [1] - If a tarball was downloaded, it unpacks it with tar xzf and then removes the sha256 + tarball. [1] - If the downloaded binary name is not “crossplane” (e.g., crank for older versions), it renames it to crossplane. [1] 6) Finalization - It chmod +x crossplane. [1] - It prints instructions to move it to /usr/local/bin and run crossplane --help. [1] How this relates to official documentation (current mechanism) - Crossplane’s CLI docs describe using an install script from the raw GitHub URL, e.g. curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | sh, and explain that the script detects CPU architecture and downloads the latest stable release. [2] - The docs also describe XP_CHANNEL and XP_VERSION variables for selecting other CLI versions/branches, matching the same variables used inside install.sh. [2] Note on “today’s” date / version targeting - Your request specifies v2.0.2, but the web results I could retrieve in the first search round show the install.sh content from the repository’s master branch (URL ending in /crossplane/master/install.sh). The code patterns above are therefore grounded in that retrieved install.sh content; the same script template is what the docs refer to for installing any version by pinning XP_VERSION/XP_CHANNEL or by pointing at a release-specific install.sh URL. [1][2]
Citations:
- 1: https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh
- 2: https://docs.crossplane.io/v2.0/cli/
🌐 Web query:
Does raw.githubusercontent.com/crossplane/crossplane/v2.0.2/install.sh exist? 404 or valid
💡 Result:
The URL raw.githubusercontent.com/crossplane/crossplane/v2.0.2/install.sh does not exist (it returns 404), while the install script does exist for other paths/tags (e.g., master has https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh). [1] What I found: 1) Crossplane’s official docs reference the installer at raw.githubusercontent.com/crossplane/crossplane/main/install.sh / install.sh from the repository’s main branch (not v2.0.2). [2] 2) I could locate the repository’s install.sh content on master (but not on the v2.0.2 tag path). [1] So for v2.0.2 specifically, expect 404 at that raw.githubusercontent.com path.
Citations:
- 1: https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh
- 2: https://docs.crossplane.io/v2.0/cli/
🌐 Web query:
Crossplane CLI docs pin install.sh commit hash recommended
💡 Result:
There is no official recommendation to pin the Crossplane install.sh script to a specific commit hash, and the script is intended to be fetched from the main branch to ensure the most recent installation logic is used [1][2][3]. For production or reproducible environments where you require a consistent CLI version, the official documentation instead recommends pinning the version of the Crossplane CLI binary itself using the XP_VERSION environment variable [3][4]. To install a specific version, use: curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | XP_VERSION=v1.20.0 sh This ensures that regardless of updates to the install.sh script, you receive the specific binary version desired [3][4]. While the script is currently maintained in the main branch of the Crossplane repository [1][2], security discussions have noted the risks of piping directly to shell and have proposed future improvements for integrity verification [5]. Always prefer fetching official release versions as documented in the Crossplane CLI reference [3][4].
Citations:
- 1: https://github.com/crossplane/crossplane/blob/main/install.sh
- 2: https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh
- 3: https://docs.crossplane.io/v1.20/cli/
- 4: https://docs.crossplane.io/latest/cli/
- 5: design: Add a one-pager regarding versioning and releasing the CLI crossplane/crossplane#7350
Avoid executing an unpinned Crossplane installer via curl | sh in on-pr workflow.
Line 60 downloads https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh (moving ref) and executes it via | ... sh; while XP_VERSION=v2.0.2 pins the downloaded CLI binary, the installer script itself remains mutable, weakening provenance/reproducibility.
- Download
install.shto a file (withcurl --fail --location --retry ...) and execute the saved script instead of piping tosh. - Pin
install.shto an immutable ref (commit SHA) rather thanmaster(the.../v2.0.2/install.shpath returns 404).
🤖 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/on-pr.yaml around lines 58 - 62, The workflow step
"Install Crossplane CLI" currently pipes the mutable installer at
.../master/install.sh into sh; instead download the installer to a file and
execute that saved file, and pin the installer URL to an immutable commit SHA
instead of master. Replace the curl | sh usage by using curl --fail --location
--retry (or similar) to fetch the installer to a local file (e.g., install.sh),
make it executable, and run it with XP_VERSION=v2.0.2 ./install.sh; update the
URL to point to the specific commit SHA for the installer script in the
crossplane repo to ensure reproducibility.
| - name: Checkout | ||
| uses: actions/checkout@v6 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the workflow file around the referenced lines
FILE=".github/workflows/on-push-main.yaml"
echo "== File: $FILE =="
if [ -f "$FILE" ]; then
nl -ba "$FILE" | sed -n '1,120p'
else
echo "Missing: $FILE"
fi
# Also list other workflows that might share the same patterns (for comparison)
echo
echo "== Other workflows referencing this file (if any) =="
fd .github/workflows -t f | sortRepository: hops-ops/aws-crossplane-stack
Length of output: 182
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE=".github/workflows/on-push-main.yaml"
echo "== File: $FILE =="
if [ -f "$FILE" ]; then
# Print with line numbers without nl
awk '{printf "%d\t%s\n", NR, $0}' "$FILE" | sed -n '1,140p'
else
echo "Missing: $FILE"
fi
echo
echo "== Repo .github/workflows files =="
fd ".github/workflows" -t f | sort || trueRepository: hops-ops/aws-crossplane-stack
Length of output: 3891
🌐 Web query:
GitHub Actions checkout persist-credentials default value actions/checkout@v6
💡 Result:
For actions/checkout@v6, the persist-credentials input’s “default value” is effectively true (enabled) when you don’t set it in your workflow, because the action.yml defines persist-credentials with a default of an empty string (meaning use the action’s built-in default behavior) and the v6 README describes that credentials are persisted unless you opt out with persist-credentials: false [1][2]. What the action does: - The auth token is persisted in the local git config so that subsequent authenticated git commands work in the job; the token is removed during post-job cleanup. You can disable this by setting persist-credentials: false [2]. So if you write: - uses: actions/checkout@v6 (without a persist-credentials key), it behaves as “persist-credentials enabled” [1][2].
Citations:
- 1: https://raw.githubusercontent.com/actions/checkout/v6/action.yml
- 2: https://github.com/actions/checkout
Harden checkout credentials and pin third-party actions to immutable refs
on-push-main.yamlusesactions/checkout@v6withoutpersist-credentials: false, so checkout credentials are persisted by default on the main push path.actions/checkout@v6(line 31),actions/cache@v5(line 34),docker/login-action@v3.7.0(line 60), andupbound/action-up-project@v1.1.2(line 67) are pinned only to version tags (not commit SHAs), leaving avoidable supply-chain risk.
🧰 Tools
🪛 zizmor (1.25.2)
[warning] 30-31: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
[error] 31-31: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
🤖 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/on-push-main.yaml around lines 30 - 31, Update the
checkout step and third-party action pins to harden credentials and reduce
supply-chain risk: for the Checkout step (actions/checkout@v6) add
persist-credentials: false to prevent token persistence, and replace the tag
pins for actions/checkout, actions/cache@v5, docker/login-action@v3.7.0, and
upbound/action-up-project@v1.1.2 with their corresponding immutable commit SHAs
(pin each action to a specific rev) while preserving existing inputs and
behavior.
Source: Linters/SAST tools
| - name: Install Crossplane CLI | ||
| run: | | ||
| curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh \ | ||
| | XP_VERSION=v2.0.2 sh |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show the referenced workflow lines
sed -n '1,120p' .github/workflows/on-push-main.yaml | nl -ba | sed -n '40,80p'
# Search for other uses of the Crossplane install script URL (master or otherwise)
rg -n "crossplane/crossplane/(master|main)/install\.sh|XP_VERSION|Install Crossplane CLI|install\.sh \\\"" -S .github/workflows . || true
# Search for any other Crossplane installer/provenance handling
rg -n "crossplane.*install\.sh|XP_VERSION=" -S .github/workflows . || trueRepository: hops-ops/aws-crossplane-stack
Length of output: 116
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Workflow snippet around lines 50-70 ==="
# Use sed with explicit range; no line-number printer needed
sed -n '45,75p' .github/workflows/on-push-main.yaml
echo
echo "=== Search for Crossplane installer URL patterns ==="
rg -n "crossplane/crossplane/.*/install\.sh|XP_VERSION=|Install Crossplane CLI|XP_VERSION=" .github/workflows -S || true
echo
echo "=== Search repo for 'install.sh' invocations ==="
rg -n "install\.sh" . -S || trueRepository: hops-ops/aws-crossplane-stack
Length of output: 1748
Pin the Crossplane installer source instead of using the moving master branch
The workflow downloads https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh and pipes it directly to sh, making CI depend on a moving branch even though XP_VERSION=v2.0.2 is set. This same pattern exists in both .github/workflows/on-push-main.yaml and .github/workflows/on-pr.yaml.
- name: Install Crossplane CLI
run: |
curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh \
| XP_VERSION=v2.0.2 shUse a pinned commit/tag for the installer URL (and ideally verify provenance, e.g., checksum/signature) to keep branch-to-branch CI deterministic and safer.
🤖 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/on-push-main.yaml around lines 54 - 57, The "Install
Crossplane CLI" step currently curls the installer from the moving master
branch; update the run command in that step (and the identical step in the other
workflow) to fetch the installer from a pinned tag or commit URL (e.g., replace
.../master/install.sh with the specific release tag or commit SHA for
Crossplane), and optionally add a checksum or signature verification step after
download before piping to sh to ensure provenance.
| if up composition render "$@" >"$output"; then | ||
| cat "$output" | ||
| rm -f "$output" | ||
| return 0 | ||
| fi | ||
|
|
||
| status=$? | ||
| rm -f "$output" | ||
| if [ "$attempt" -ge "$max_attempts" ]; then | ||
| return "$status" | ||
| fi |
There was a problem hiding this comment.
render_with_retry can return the wrong status after a failed render.
Line 114 captures $? after the if compound, so the final failure path can return a non-render status and let validation proceed incorrectly. Capture the render exit code inside the else branch.
Suggested fix
while true; do
- if up composition render "$@" >"$output"; then
+ if up composition render "$@" >"$output"; then
cat "$output"
rm -f "$output"
return 0
+ else
+ status=$?
fi
-
- status=$?
rm -f "$output"
if [ "$attempt" -ge "$max_attempts" ]; then
return "$status"
fi🤖 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 `@scripts/ci-validate-all.sh` around lines 108 - 118, The render step in
render_with_retry captures $? after the entire if compound which can grab the
wrong exit code; move the capture of the render command's exit status
(status=$?) into the else branch immediately after the failed "up composition
render \"$@\" >\"$output\"" so you record the render exit code instead of the
if's exit code, then proceed to rm -f "$output" and the existing retry/return
logic using that status variable.
Published Crossplane PackageThe following Crossplane package was published as part of this PR: Package: ghcr.io/hops-ops/aws-crossplane-stack:pr-22-0dd5d6fbc4fe8c435a51c8a9582d00477daf98da |
Summary
Verification
Notes
Summary by CodeRabbit