bump github actions, improve security#1273
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
📝 WalkthroughWalkthroughGitHub Actions workflows are updated with explicit read-only permissions and credential isolation across all jobs. Action versions are upgraded (checkout and setup-go to v6, github-script to v9). The e2e workflow is refined to trigger only on pull requests to ChangesGitHub Actions and Container Hardening
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 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 unit tests (beta)
Warning Review ran into problems🔥 ProblemsLinked repositories: Your configuration references 2 linked repositories, but your current plan allows 1. Analyzed 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: 7
🤖 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/build_image_pr.yml:
- Around line 19-21: Replace the mutable tag usage of the GitHub Action
"actions/checkout@v6" with a full-length commit SHA to pin the action immutably;
locate the workflow step referencing actions/checkout (search for
"actions/checkout@v6") and update the "uses" value to the canonical commit SHA
for the desired actions/checkout release, keeping the existing "with:
persist-credentials: false" configuration unchanged.
In @.github/workflows/pull_request_e2e.yml:
- Around line 23-25: The YAML under the checkout step has misaligned keys: move
the with: and persist-credentials: keys to the same indentation level as uses:
so they match the setup-go step pattern; adjust the indentation for the with
block (and its persist-credentials key) to align with uses: so the checkout step
is valid YAML using the keys uses, with, and persist-credentials at the same
level.
In @.github/workflows/pull_request.yml:
- Around line 19-25: The workflow uses mutable tags for actions
actions/setup-go@v6 and actions/checkout@v6; replace those mutable tags with the
corresponding full commit SHAs to pin the actions immutably. Locate the uses:
the setup step referencing "actions/setup-go@v6" and the checkout step
referencing "actions/checkout@v6" and update the value after the @ to the full
commit SHA from each action's GitHub repo (use the latest secure commit you
trust), keeping the existing with: blocks unchanged.
In @.github/workflows/push_image_pr.yml:
- Around line 37-40: Replace the mutable tag "actions/github-script@v9" with a
pinned commit SHA reference so the workflow uses a fixed, auditable version;
locate the step that currently uses actions/github-script@v9 and update the
action reference to the corresponding commit SHA (matching the project's pattern
used for other actions like docker/login-action or codecov/codecov-action) and
ensure the new SHA is the latest verified commit from the actions/github-script
repository.
In @.github/workflows/push_image.yml:
- Around line 49-51: The workflow currently uses actions/setup-go@v6 with
go-version: '1.25' and leaves the setup-go cache enabled; update the step that
references actions/setup-go@v6 to explicitly disable its module cache by adding
the cache: 'false' (or equivalent cache disabling key) under the with block so
the CODECOV_TOKEN-handling job cannot be exposed via a poisoned cache.
- Around line 23-25: Replace mutable action tags with immutable commit SHAs:
locate any uses of actions/checkout@v6 and actions/setup-go@v6 (and any other
actions in these workflows using version tags) and change them to the
corresponding full commit SHA pin (the same style used for docker/login-action
and codecov/codecov-action) so the workflow pins are immutable; update each
workflow file where these actions appear to use the full commit SHA for
consistency and repeatability.
In @.github/workflows/release.yml:
- Around line 17-19: Replace mutable tag usages of actions with pinned commit
SHAs: update the workflow steps referencing actions/checkout@v6 and
actions/github-script@v9 to use the full commit SHA form (the same pattern used
for docker/login-action@465a07...), i.e., find the steps that call
"actions/checkout@v6" and "actions/github-script@v9" and replace the version
tags with their corresponding commit SHA values so the workflow uses immutable,
pinned action SHAs.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0bd4eb40-f768-456c-9740-4440534da892
📒 Files selected for processing (8)
.github/workflows/build_image_pr.yml.github/workflows/pull_request.yml.github/workflows/pull_request_e2e.yml.github/workflows/push_image.yml.github/workflows/push_image_pr.yml.github/workflows/release.ymlcontrib/docker/Dockerfilecontrib/docker/Dockerfile.downstream
| - uses: actions/checkout@v6 | ||
| with: | ||
| persist-credentials: false |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Read the workflow file to verify the exact content at lines 19-21
cat -n .github/workflows/build_image_pr.yml | head -30Repository: netobserv/flowlogs-pipeline
Length of output: 1173
🏁 Script executed:
#!/bin/bash
# Check other workflow files to see the pattern across the repo
find .github/workflows -name "*.yml" -o -name "*.yaml" | sortRepository: netobserv/flowlogs-pipeline
Length of output: 318
🏁 Script executed:
#!/bin/bash
# Check how actions/checkout is used in other workflows
grep -r "actions/checkout" .github/workflows/ -A 2Repository: netobserv/flowlogs-pipeline
Length of output: 1203
🏁 Script executed:
#!/bin/bash
# Check if ANY workflows use pinned commit SHAs
grep -r "actions/" .github/workflows/ | grep -E "@[a-f0-9]{40}|@[a-f0-9]{7}" || echo "No pinned SHAs found"Repository: netobserv/flowlogs-pipeline
Length of output: 92
🏁 Script executed:
#!/bin/bash
# Check how the operator repo uses actions/checkout
grep -r "actions/checkout" .github/workflows/ 2>/dev/null | head -5 || echo "No .github/workflows found or no checkout usage"Repository: netobserv/netobserv-operator
Length of output: 411
Pin actions/checkout to an immutable commit SHA.
The action uses mutable tag @v6, which can be updated. Pin to a full-length commit SHA for immutability and to pass unpinned-action security checks.
Suggested fix
- - uses: actions/checkout@v6
+ - uses: actions/checkout@<commit-sha> # v6
with:
persist-credentials: false🧰 Tools
🪛 zizmor (1.25.2)
[error] 19-19: 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/build_image_pr.yml around lines 19 - 21, Replace the
mutable tag usage of the GitHub Action "actions/checkout@v6" with a full-length
commit SHA to pin the action immutably; locate the workflow step referencing
actions/checkout (search for "actions/checkout@v6") and update the "uses" value
to the canonical commit SHA for the desired actions/checkout release, keeping
the existing "with: persist-credentials: false" configuration unchanged.
| uses: actions/setup-go@v6 | ||
| with: | ||
| go-version: '1.25' | ||
| - name: checkout | ||
| uses: actions/checkout@v3 | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| persist-credentials: false |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check the workflow file content around the specified lines
cat -n .github/workflows/pull_request.yml | sed -n '1,50p'Repository: netobserv/flowlogs-pipeline
Length of output: 1191
🏁 Script executed:
#!/bin/bash
# Find all workflow files
find .github/workflows -name "*.yml" -o -name "*.yaml" | head -20Repository: netobserv/flowlogs-pipeline
Length of output: 318
🏁 Script executed:
#!/bin/bash
# Check other workflow files for action pinning patterns
for file in $(find .github/workflows -type f \( -name "*.yml" -o -name "*.yaml" \)); do
echo "=== $file ==="
grep -E "uses: .+@[a-f0-9]{40}|uses: .+@v[0-9]+" "$file" | head -10
doneRepository: netobserv/flowlogs-pipeline
Length of output: 1395
🌐 Web query:
GitHub Actions security best practices pinning commit SHA
💡 Result:
Pinning GitHub Actions to a full-length commit SHA is a critical security best practice to prevent supply chain attacks [1][2][3][4]. Because Git tags are mutable and can be forcibly moved or deleted by an attacker who compromises a repository, relying on tag-based references (like @v4) can lead to the silent execution of malicious code [5][6][7][8]. Why Pinning to Commit SHA is Necessary: 1. Immutability: Unlike tags, a specific commit SHA points to a unique, immutable snapshot of the repository code [3][6][7]. This guarantees that your workflow executes the exact code you have reviewed and validated, preventing attackers from injecting malicious changes into existing tags [3][9][4]. 2. Supply Chain Protection: Recent security incidents have demonstrated that attackers frequently target popular actions by force-pushing malicious commits to existing release tags, which immediately compromises all workflows using those tags [5][8]. 3. Policy Enforcement: GitHub now supports organization-level and repository-level policies that can strictly enforce SHA pinning [2][9][4]. When enabled, any workflow attempting to use a mutable tag or branch reference will fail, ensuring compliance across your entire environment [2][6][9]. How to Implement and Maintain Pinned Actions: - Standard Format: Always use the full-length commit SHA and include a comment indicating the corresponding version for readability and maintenance [10][9]. Example: uses: actions/checkout@b4ffde6 # v4.1.1 - Automated Updates: Because manual updates can be tedious, utilize automated dependency management tools like Dependabot or Renovate. Configure these tools to create pull requests for action updates, allowing you to review changes before merging [1][10][6][7]. - Adopt Cooldown Periods: To further mitigate risk, consider using "cooldown" policies (e.g., waiting 7-14 days after a new action version is released) before upgrading. This window helps identify and avoid malicious updates that are often discovered shortly after release [11]. - Verify Sources: When pinning, ensure the SHA originates from the legitimate, verified repository of the action, not a fork [4]. By enforcing SHA pinning, you transition from a model of blind trust in external tags to a verifiable, secure CI/CD pipeline [12][11].
Citations:
- 1: Pin all GitHub Actions to immutable SHA commits for supply chain security github/gh-aw#5691
- 2: https://github.blog/changelog/2025-08-15-github-actions-policy-now-supports-blocking-and-sha-pinning-actions/
- 3: https://www.stepsecurity.io/blog/pinning-github-actions-for-enhanced-security-a-complete-guide
- 4: https://docs.github.com/en/actions/reference/security/secure-use
- 5: https://dev.to/kanywst/hacking-github-from-tag-rewrites-to-dangling-commits-where-the-git-protocol-trusts-you-without-2o4h
- 6: https://www.romainlespinasse.dev/posts/github-actions-commit-sha-pinning/
- 7: https://blog.rafaelgss.dev/why-you-should-pin-actions-by-commit-hash
- 8: https://gbhackers.com/compromised-github-action/
- 9: https://dev.to/ciberconscientes/github-actions-why-you-should-pin-your-actions-to-a-specific-version-1513
- 10: Pin GitHub Actions to commit SHAs in release workflow github/gh-aw#10021
- 11: https://www.wiz.io/blog/github-actions-security-guide
- 12: https://dev.to/nkuziev-sec/why-fixed-container-image-versions-matter-lessons-from-the-trivy-supply-chain-attack-29ke
Pin actions/setup-go and actions/checkout to commit SHAs.
Lines 19 and 23 reference these actions with mutable tags (@v6), which are vulnerable to supply chain attacks. Git tags can be forcibly moved or deleted by compromised maintainers, allowing malicious code injection. Pinning to full-length commit SHAs (as already done for codecov/codecov-action on line 33) ensures immutability and prevents this attack vector.
Suggested fix
- name: set up go 1.x
- uses: actions/setup-go@v6
+ uses: actions/setup-go@cd3185276690dc3f1bd21e64f81949e4792277e5 # v6.0.5
with:
go-version: '1.25'
- name: checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@d632683dd7b4114ad4ce1480623a91578e9b1881 # v6.1.0
with:
persist-credentials: false🧰 Tools
🪛 zizmor (1.25.2)
[error] 19-19: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 23-23: 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/pull_request.yml around lines 19 - 25, The workflow uses
mutable tags for actions actions/setup-go@v6 and actions/checkout@v6; replace
those mutable tags with the corresponding full commit SHAs to pin the actions
immutably. Locate the uses: the setup step referencing "actions/setup-go@v6" and
the checkout step referencing "actions/checkout@v6" and update the value after
the @ to the full commit SHA from each action's GitHub repo (use the latest
secure commit you trust), keeping the existing with: blocks unchanged.
| - uses: actions/github-script@v9 | ||
| with: | ||
| github-token: ${{secrets.GITHUB_TOKEN}} | ||
| script: | |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check the current state of the workflow file
cat -n .github/workflows/push_image_pr.yml | sed -n '30,45p'Repository: netobserv/flowlogs-pipeline
Length of output: 816
🏁 Script executed:
#!/bin/bash
# Search for other uses of actions/github-script in workflows
find .github/workflows -name "*.yml" -o -name "*.yaml" | xargs grep -n "actions/github-script" | head -20Repository: netobserv/flowlogs-pipeline
Length of output: 221
🏁 Script executed:
#!/bin/bash
# Check for other workflow files to see pinning patterns
find .github/workflows -name "*.yml" -o -name "*.yaml" | head -10Repository: netobserv/flowlogs-pipeline
Length of output: 318
🏁 Script executed:
#!/bin/bash
# Check if there's a security policy or pinning requirements document
find . -maxdepth 2 -type f \( -name "*.md" -o -name "*.yml" -o -name "*.yaml" \) | grep -iE "(policy|security|SECURITY)" | head -10Repository: netobserv/flowlogs-pipeline
Length of output: 85
🏁 Script executed:
#!/bin/bash
# Sample a workflow to see how other actions are pinned
cat -n .github/workflows/push_image.yml | head -60Repository: netobserv/flowlogs-pipeline
Length of output: 2511
🏁 Script executed:
#!/bin/bash
# Check what versions/shas other actions use in the repo
grep -n "uses: actions/" .github/workflows/*.yml | head -30Repository: netobserv/flowlogs-pipeline
Length of output: 1092
🏁 Script executed:
#!/bin/bash
# Check the SECURITY.md file for action pinning policy
cat SECURITY.mdRepository: netobserv/flowlogs-pipeline
Length of output: 902
🏁 Script executed:
#!/bin/bash
# Check if there's a policy or config file for dependabot or renovate
find . -maxdepth 2 -type f \( -name ".dependabot*" -o -name "renovate.json" -o -name ".github/dependabot*" \) 2>/dev/nullRepository: netobserv/flowlogs-pipeline
Length of output: 87
🏁 Script executed:
#!/bin/bash
# Look at the complete push_image_pr.yml to understand context
cat -n .github/workflows/push_image_pr.ymlRepository: netobserv/flowlogs-pipeline
Length of output: 2434
🏁 Script executed:
#!/bin/bash
# Check renovate configuration for action pinning policy
cat renovate.jsonRepository: netobserv/flowlogs-pipeline
Length of output: 875
🏁 Script executed:
#!/bin/bash
# Check if the operator repo has similar patterns for comparison
rg "actions/github-script" ../netobserv-operator/.github 2>/dev/null || echo "Path not accessible, trying alternative"Repository: netobserv/flowlogs-pipeline
Length of output: 111
Pin actions/github-script to a commit SHA for consistency with project supply-chain practices.
This repository pins third-party actions (e.g., docker/login-action, codecov/codecov-action) to commit SHAs. The actions/github-script@v9 reference at line 37 uses a mutable tag and should follow the same pattern.
🧰 Tools
🪛 zizmor (1.25.2)
[error] 37-37: 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/push_image_pr.yml around lines 37 - 40, Replace the
mutable tag "actions/github-script@v9" with a pinned commit SHA reference so the
workflow uses a fixed, auditable version; locate the step that currently uses
actions/github-script@v9 and update the action reference to the corresponding
commit SHA (matching the project's pattern used for other actions like
docker/login-action or codecov/codecov-action) and ensure the new SHA is the
latest verified commit from the actions/github-script repository.
| uses: actions/checkout@v6 | ||
| with: | ||
| persist-credentials: false |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n .github/workflows/push_image.ymlRepository: netobserv/flowlogs-pipeline
Length of output: 2722
🏁 Script executed:
fd -e yml -path '.github/workflows/*' -type f | head -10Repository: netobserv/flowlogs-pipeline
Length of output: 240
🏁 Script executed:
find .github/workflows -name "*.yml" -o -name "*.yaml"Repository: netobserv/flowlogs-pipeline
Length of output: 318
🏁 Script executed:
cat -n .github/workflows/pull_request.yml | head -60Repository: netobserv/flowlogs-pipeline
Length of output: 1191
🏁 Script executed:
find . -maxdepth 2 -name "SECURITY*" -o -name "CONTRIBUTING*" -o -name ".github/SECURITY*" 2>/dev/nullRepository: netobserv/flowlogs-pipeline
Length of output: 103
🏁 Script executed:
cat -n SECURITY.md && echo "---CONTRIBUTING---" && cat -n CONTRIBUTING.mdRepository: netobserv/flowlogs-pipeline
Length of output: 6474
Pin all changed GitHub Actions to immutable commit SHAs.
actions/checkout@v6 and actions/setup-go@v6 use mutable version tags. Other actions in the same workflows (docker/login-action, codecov/codecov-action) are already pinned to full commit SHAs—apply the same pattern here for consistency and to prevent unintended updates from branch tag reassignment.
Lines 23, 49, 53 in push_image.yml and corresponding lines in other workflows need updates.
Example fix
- uses: actions/checkout@v6
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c112766 # v6- uses: actions/setup-go@v6
+ uses: actions/setup-go@0a12ed9d6470b34f1be9a3d8b9e59f8fa9130861 # v6🧰 Tools
🪛 zizmor (1.25.2)
[error] 23-23: 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/push_image.yml around lines 23 - 25, Replace mutable
action tags with immutable commit SHAs: locate any uses of actions/checkout@v6
and actions/setup-go@v6 (and any other actions in these workflows using version
tags) and change them to the corresponding full commit SHA pin (the same style
used for docker/login-action and codecov/codecov-action) so the workflow pins
are immutable; update each workflow file where these actions appear to use the
full commit SHA for consistency and repeatability.
| uses: actions/setup-go@v6 | ||
| with: | ||
| go-version: '1.25' |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find and read the push_image workflow file
fd -t f "push_image.yml" .github/workflows/Repository: netobserv/flowlogs-pipeline
Length of output: 104
🏁 Script executed:
#!/bin/bash
# Read the push_image.yml file to verify content around lines 49-51
cat -n .github/workflows/push_image.ymlRepository: netobserv/flowlogs-pipeline
Length of output: 2722
🏁 Script executed:
#!/bin/bash
# Search for codecov references in the workflow
rg -i "codecov" .github/workflows/Repository: netobserv/flowlogs-pipeline
Length of output: 573
🏁 Script executed (no clone):
#!/bin/bash
# Search for setup-go v6 documentation and caching behavior
curl -s "https://raw.githubusercontent.com/actions/setup-go/main/README.md" | head -100
Length of output: 4041
🌐 Web query:
setup-go@v6 cache default behavior security
💡 Result:
Default behavior (actions/setup-go@v6): - Caching is enabled by default (cache input defaults to true). The action’s caching can be disabled via cache: false. [1] - For the cache key for Go modules, setup-go@v6 uses the hash of go.mod by default (not go.sum). [1][2] - It checks/uses its local tool cache first; if that version isn’t available, it pulls from the go-versions repository, and if needed falls back to downloading directly from Go distribution. [1] Security-relevant implications of the default cache behavior: - Because caching is on by default, workflows will restore previously cached Go modules/build outputs and may avoid re-downloading dependencies when the cache key matches. This increases the importance of ensuring your dependency files (go.mod/go.sum) accurately and securely reflect the dependencies you intend to build, since the cache key is derived from go.mod by default. [1][2] - The action documentation also notes that if caching cannot be performed for any reason, it logs a warning and continues the workflow. [1] This means you should not treat “warning in logs” as a guaranteed cache restore; builds may fall back to downloading/building normally. If you want different cache-key inputs: - Use cache-dependency-path to point the action at other dependency file(s) (the docs describe it as supporting globs and multiple dependency files). [1] - In particular, to base the cache key on go.sum instead of go.mod, configure cache-dependency-path accordingly. [1][2]
Citations:
🌐 Web query:
GitHub Actions cache poisoning risk setup-go
💡 Result:
GitHub Actions cache poisoning is a security vulnerability where an attacker injects malicious content into the shared repository cache [1][2][3]. Because the GitHub Actions cache is repository-wide and not strictly scoped by trust level, event, or workflow, a compromised, low-privilege workflow (such as one running on an untrusted pull request) can write entries that a higher-privilege workflow (such as a release pipeline) subsequently restores and executes [4][3][5]. When using actions/setup-go, the cache=true option automatically manages the Go module cache and build cache [6][7]. This creates a specific risk surface because these caches are restored and used by the Go toolchain [2][7]. If an attacker successfully poisons these cache entries, they can force the Go toolchain to use malicious dependencies or binary artifacts, leading to potential code execution within the privileged workflow [2][3]. Key security considerations for setup-go and cache management include: 1. High-Privilege Workflows: Security best practices dictate that caching should be disabled (cache: false) in sensitive workflows, such as those that publish artifacts or handle production secrets [6][5]. The performance benefit of caching in these workflows is often outweighed by the supply chain risk [6]. 2. Cache Scoping: Relying on default cache keys (which are often based on hashFiles('go.mod') or go.sum) can be risky if multiple workflows or branches share the same key [4][3]. Implementing custom, isolated cache namespaces (e.g., prefixing keys by trigger or branch) is recommended to prevent unintended collision between untrusted and trusted workflows [4]. 3. Mitigation Strategies: - Disable caching in critical/release pipelines [6][5]. - Use strict cache key schemas that include workflow-specific identifiers rather than relying solely on file hashes [4]. - Periodically purge caches to limit the window of opportunity for an attacker [4]. - For highly sensitive builds, accept longer build times by avoiding caches entirely to ensure build integrity [4][2]. 4. Evolution of Protections: GitHub has implemented protections over time, such as preventing cache writes after the originating job has completed, which increases the difficulty of cache stuffing attacks [8][3]. However, the architectural risk of shared, unverified caches remains [4][3]. Developers should monitor their workflows for signs of cache manipulation and use tools like zizmor to detect potential security misconfigurations, including unsafe cache usage in release-critical workflows [6].
Citations:
- 1: https://codeql.github.com/codeql-query-help/actions/actions-cache-poisoning-direct-cache/
- 2: https://adnanthekhan.com/2024/05/06/the-monsters-in-your-build-cache-github-actions-cache-poisoning/
- 3: https://cloud.hacktricks.wiki/en/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-cache-poisoning.html
- 4: https://safeguard.sh/resources/blog/github-actions-cache-poisoning-attack-class-2025
- 5: https://cheatsheetseries.owasp.org/cheatsheets/GitHub_Actions_Security_Cheat_Sheet.html
- 6: Disable Go module caching in release workflow to prevent cache poisoning github/gh-aw#5872
- 7: Docs: guidelines for configuring Go module/build cache in a security-conscious way github/gh-aw#27886
- 8: https://github.com/AdnaneKhan/ActionsCacheBlasting
Disable setup-go cache in this workflow.
The codecov job handles the CODECOV_TOKEN secret. Keeping caching enabled creates a cache-poisoning risk—attackers could poison the shared cache to inject malicious code that executes with secret access. Disabling cache is a standard security practice for secret-handling workflows.
Suggested fix
- name: set up go 1.x
uses: actions/setup-go@v6
with:
go-version: '1.25'
+ cache: false📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.25' | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.25' | |
| cache: false |
🧰 Tools
🪛 zizmor (1.25.2)
[error] 49-49: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 49-49: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default
(cache-poisoning)
🤖 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/push_image.yml around lines 49 - 51, The workflow
currently uses actions/setup-go@v6 with go-version: '1.25' and leaves the
setup-go cache enabled; update the step that references actions/setup-go@v6 to
explicitly disable its module cache by adding the cache: 'false' (or equivalent
cache disabling key) under the with block so the CODECOV_TOKEN-handling job
cannot be exposed via a poisoned cache.
| uses: actions/checkout@v6 | ||
| with: | ||
| persist-credentials: false |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Read the release.yml file to verify the actions and their pins
cat -n .github/workflows/release.yml | head -100Repository: netobserv/flowlogs-pipeline
Length of output: 2915
Pin changed actions to full commit SHAs.
actions/checkout@v6 and actions/github-script@v9 use mutable version tags instead of pinned commit SHAs, violating unpinned-action policy. This workflow already uses pinned SHAs elsewhere (e.g., docker/login-action@465a07...), so follow that pattern.
Suggested fix
- - name: checkout
- uses: actions/checkout@v6
+ - name: checkout
+ uses: actions/checkout@<full-length-commit-sha> # v6
with:
persist-credentials: false
@@
- - name: upload binaries
- uses: actions/github-script@v9
+ - name: upload binaries
+ uses: actions/github-script@<full-length-commit-sha> # v9
with:
github-token: ${{secrets.GITHUB_TOKEN}}🧰 Tools
🪛 zizmor (1.25.2)
[error] 17-17: 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/release.yml around lines 17 - 19, Replace mutable tag
usages of actions with pinned commit SHAs: update the workflow steps referencing
actions/checkout@v6 and actions/github-script@v9 to use the full commit SHA form
(the same pattern used for docker/login-action@465a07...), i.e., find the steps
that call "actions/checkout@v6" and "actions/github-script@v9" and replace the
version tags with their corresponding commit SHA values so the workflow uses
immutable, pinned action SHAs.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/pull_request_e2e.yml:
- Around line 19-25: Update the workflow to pin the GitHub Actions to immutable
commit SHAs instead of mutable tags: replace uses: actions/setup-go@v6 with
uses: actions/setup-go@<full-commit-sha-for-v6> and replace uses:
actions/checkout@v6 with uses: actions/checkout@<full-commit-sha-for-v6>; keep
the existing with: blocks (go-version and persist-credentials) unchanged, and
fetch the exact SHAs from the v6 release pages for actions/setup-go and
actions/checkout before committing.
In `@contrib/docker/Dockerfile`:
- Line 21: The Dockerfile sets USER 65532:65532 which is good for security but
requires writable output directories for UID 65532; update the image build to
create any application output directories (e.g., locations for location DBs,
Grafana dashboards, metrics) and set their ownership or permissions for UID
65532 before switching user (create dirs and chown/chmod them), and document
that mounted volumes must be writable by UID 65532; look for the USER
65532:65532 directive to add the mkdir + chown/chmod steps or add runtime checks
to ensure writability.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4279a399-4e46-4a84-89fa-9f6f394daeb1
📒 Files selected for processing (8)
.github/workflows/build_image_pr.yml.github/workflows/pull_request.yml.github/workflows/pull_request_e2e.yml.github/workflows/push_image.yml.github/workflows/push_image_pr.yml.github/workflows/release.ymlcontrib/docker/Dockerfilecontrib/docker/Dockerfile.downstream
✅ Files skipped from review due to trivial changes (1)
- contrib/docker/Dockerfile.downstream
| uses: actions/setup-go@v6 | ||
| with: | ||
| go-version: '1.25' | ||
| - name: checkout | ||
| uses: actions/checkout@v3 | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| persist-credentials: false |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if the workflow file exists and examine the relevant lines
if [ -f .github/workflows/pull_request_e2e.yml ]; then
echo "File found. Reading lines 1-30:"
sed -n '1,30p' .github/workflows/pull_request_e2e.yml
else
echo "File not found at expected path"
fiRepository: netobserv/flowlogs-pipeline
Length of output: 658
🏁 Script executed:
#!/bin/bash
# Find all workflow files
find .github/workflows -name "*.yml" -o -name "*.yaml" | head -20Repository: netobserv/flowlogs-pipeline
Length of output: 318
🏁 Script executed (no clone):
#!/bin/bash
# Look up current SHAs for the v6 releases of these actions
# setup-go v6
curl -s https://api.github.com/repos/actions/setup-go/releases/tags/v6 | jq -r '.target_commitish' 2>/dev/null || echo "Could not fetch setup-go v6 commit"
# checkout v6
curl -s https://api.github.com/repos/actions/checkout/releases/tags/v6 | jq -r '.target_commitish' 2>/dev/null || echo "Could not fetch checkout v6 commit"
Length of output: 41
🏁 Script executed:
#!/bin/bash
# Check other workflow files for action usage patterns
echo "=== Checking build_image_pr.yml ==="
grep -E "uses: actions/" .github/workflows/build_image_pr.yml | head -10
echo ""
echo "=== Checking push_image.yml ==="
grep -E "uses: actions/" .github/workflows/push_image.yml | head -10
echo ""
echo "=== Checking release.yml ==="
grep -E "uses: actions/" .github/workflows/release.yml | head -10Repository: netobserv/flowlogs-pipeline
Length of output: 456
🏁 Script executed:
#!/bin/bash
# Check if there's any config or documentation about action pinning
echo "Looking for configuration files that might define action pinning policy:"
find . -maxdepth 2 -name "*.md" -o -name ".github" -type d | head -20
echo ""
echo "Check for SECURITY.md or similar:"
ls -la | grep -i security || echo "No security file in root"
echo ""
echo "Full content of pull_request_e2e.yml to verify complete context:"
cat .github/workflows/pull_request_e2e.ymlRepository: netobserv/flowlogs-pipeline
Length of output: 1138
🏁 Script executed:
#!/bin/bash
# Check the SECURITY.md file
cat SECURITY.mdRepository: netobserv/flowlogs-pipeline
Length of output: 902
🏁 Script executed:
#!/bin/bash
# Check if there are any dependabot or action pinning configs
ls -la .github/ | grep -E "dependabot|actions|policy"
echo ""
echo "Check for dependabot.yml:"
if [ -f .github/dependabot.yml ]; then
cat .github/dependabot.yml
fi
echo ""
echo "Check for any GitHub Advanced Security or SARIF configs:"
find .github -type f | xargs grep -l "pin\|commit\|sha" 2>/dev/null || echo "No files found with pinning references"Repository: netobserv/flowlogs-pipeline
Length of output: 1033
🏁 Script executed:
#!/bin/bash
# Let's check those workflow files that mention sha/commit
echo "=== build_image_pr.yml ==="
grep -C 2 "sha\|commit" .github/workflows/build_image_pr.yml | head -20
echo ""
echo "=== push_image.yml ==="
grep -C 2 "sha\|commit" .github/workflows/push_image.yml | head -20
echo ""
echo "=== push_image_pr.yml ==="
grep -C 2 "sha\|commit" .github/workflows/push_image_pr.yml | head -20Repository: netobserv/flowlogs-pipeline
Length of output: 1778
Pin setup-go and checkout actions to immutable commit SHAs.
Both steps use mutable version tags (@v6), which violates supply-chain security best practices. Action code can change at mutable tags without workflow updates.
Replace the version tags with full commit SHAs. You can find the current SHA for each tag via:
actions/setup-go@v6: https://github.com/actions/setup-go/releases/tag/v6actions/checkout@v6: https://github.com/actions/checkout/releases/tag/v6
Suggested fix (replace SHAs with actual values)
- - name: set up go 1.x
- uses: actions/setup-go@v6
+ - name: set up go 1.x
+ uses: actions/setup-go@<commit-sha> # v6
with:
go-version: '1.25'
- name: checkout
- uses: actions/checkout@v6
+ uses: actions/checkout@<commit-sha> # v6
with:
persist-credentials: false🧰 Tools
🪛 zizmor (1.25.2)
[error] 19-19: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)
(unpinned-uses)
[error] 23-23: 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/pull_request_e2e.yml around lines 19 - 25, Update the
workflow to pin the GitHub Actions to immutable commit SHAs instead of mutable
tags: replace uses: actions/setup-go@v6 with uses:
actions/setup-go@<full-commit-sha-for-v6> and replace uses: actions/checkout@v6
with uses: actions/checkout@<full-commit-sha-for-v6>; keep the existing with:
blocks (go-version and persist-credentials) unchanged, and fetch the exact SHAs
from the v6 release pages for actions/setup-go and actions/checkout before
committing.
| FROM --platform=linux/$TARGETARCH registry.access.redhat.com/ubi9/ubi-minimal:9.8-1777460003 | ||
|
|
||
| COPY --from=builder /app/flowlogs-pipeline /app/ | ||
| USER 65532:65532 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check for file operations that might require write permissions
# Search for os.Create, os.OpenFile, os.WriteFile, os.Mkdir operations
echo "=== Checking for file write operations ==="
rg -n --type=go -C2 '\b(os\.(Create|OpenFile|WriteFile|Mkdir)|ioutil\.WriteFile)' pkg/ cmd/
# Search for log file paths or explicit directory references
echo -e "\n=== Checking for hardcoded paths ==="
rg -n --type=go -C2 '(/var/|/tmp/|/opt/|/usr/)' pkg/ cmd/
# Check if app checks for root privileges
echo -e "\n=== Checking for privilege checks ==="
rg -n --type=go -C2 '\b(os\.(Getuid|Geteuid)|syscall\.Getuid)' pkg/ cmd/
# Check for any existing test coverage of permissions
echo -e "\n=== Checking for permission-related tests ==="
rg -n --type=go -l 'TestAsNonRoot|permission|UID|GID' --glob '*_test.go'Repository: netobserv/flowlogs-pipeline
Length of output: 19760
🏁 Script executed:
#!/bin/bash
# Check the main entrypoint and application startup to understand write requirements
echo "=== Checking main.go for config/output paths ==="
rg -n --type=go -A5 -B5 'flag\.|environment|write|output|config' cmd/flowlogs-pipeline/main.go | head -100
echo -e "\n=== Checking for environment variable usage ==="
rg -n --type=go 'os\.Getenv' cmd/ pkg/config/ | head -30
echo -e "\n=== Checking if app creates its own config directories ==="
rg -n --type=go 'MkdirAll|mkdir' cmd/flowlogs-pipeline/ pkg/ | grep -v test | grep -v vendor | head -20Repository: netobserv/flowlogs-pipeline
Length of output: 4101
Ensure output directories are writable when running as UID 65532.
The USER 65532:65532 directive is a good security hardening measure. The application primarily writes to /tmp/ (world-writable) by default and has no root privilege checks, so it should run fine as non-root. However, if the deployment configures custom output paths via environment variables or config files for location databases, Grafana dashboards, or metrics files, those directories must exist and be writable by UID 65532. Verify that any mounted volumes or output paths used in your deployment have the correct permissions.
🤖 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 `@contrib/docker/Dockerfile` at line 21, The Dockerfile sets USER 65532:65532
which is good for security but requires writable output directories for UID
65532; update the image build to create any application output directories
(e.g., locations for location DBs, Grafana dashboards, metrics) and set their
ownership or permissions for UID 65532 before switching user (create dirs and
chown/chmod them), and document that mounted volumes must be writable by UID
65532; look for the USER 65532:65532 directive to add the mkdir + chown/chmod
steps or add runtime checks to ensure writability.
Summary by CodeRabbit
Release Notes