Skip to content

ci: pin GitHub Actions to full-length commit SHAs - #29

Closed
casper-phantom[bot] wants to merge 1 commit into
mainfrom
casper/feplat-5067-pin-github-actions
Closed

casper-phantom[bot] wants to merge 1 commit into
mainfrom
casper/feplat-5067-pin-github-actions

Conversation

@casper-phantom

@casper-phantom casper-phantom Bot commented Aug 5, 2026 •

Copy link
Copy Markdown

Closes FEPLAT-5067

Warning

Moderate risk: CI jobs exercise the checkout, setup-node, and cache pins on this PR, but publish.yml only runs on workflow_dispatch, so its upgraded cache and upload-artifact steps stay unverified until the next release run.

Summary

  • Pins every third-party action in ci.yml, publish.yml, and the .github/actions/setup composite action to a 40-character commit SHA, with the release tag kept in a trailing comment.
  • Moves the @v3 refs (actions/checkout, actions/setup-node, actions/cache) onto currently supported majors so the pins land on maintained code rather than freezing EOL versions; actions/cache@v3 in particular no longer works against the current cache service.
  • Each pinned action is a self-contained node24 JavaScript action with no nested uses: edges, so the dependency closure below these pins is immutable and no fork or vendoring is needed.
  • Every SHA was verified against its upstream tag via the GitHub API before pinning.

Pinned refs

Action Before After
actions/checkout @v3 (ci.yml x3), @v4 (publish.yml) 3d3c42e5aac5ba805825da76410c181273ba90b1 (v7.0.1)
actions/setup-node @v3 (setup action), @v4 (publish.yml) 820762786026740c76f36085b0efc47a31fe5020 (v7.0.0)
actions/cache @v3 (setup action, publish.yml) 55cc8345863c7cc4c66a329aec7e433d2d1c52a9 (v6.1.0)
actions/upload-artifact @v4 (publish.yml) 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a (v7.0.1)

.github/actions/setup/action.yml was not listed on the ticket but carried two more mutable refs, so it is included here.

casper-run-id: 019fd2d5-d7bc-7955-a0fc-6acb86271c70

Summary by CodeRabbit

  • Chores
    • Updated automated build, test, lint, and publishing workflows to use fixed action versions.
    • Improved workflow reproducibility and supply-chain security without changing existing behavior.

Mutable tag refs let a moved tag or compromised upstream change CI code
without a change in this repository. Pin every action to a 40-char SHA
on the current release, and move the deprecated v3 refs onto supported
majors so the pins land on maintained code.

Closes FEPLAT-5067

Co-authored-by: casper-phantom[bot] <208212958+casper-phantom[bot]@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Aug 5, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

GitHub Actions references in the reusable setup action and CI workflows now use immutable commit SHAs. Node setup, caching, checkout, and artifact upload behavior remains unchanged.

Changes

GitHub Action Pinning

Layer / File(s) Summary
Shared setup action pins
.github/actions/setup/action.yml
The reusable setup action pins actions/setup-node and actions/cache to commits for versions 7.0.0 and 6.1.0.
Workflow action pins
.github/workflows/ci.yml, .github/workflows/publish.yml
The CI and publish workflows pin checkout, Node setup, cache, and artifact upload actions to immutable commits.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: pinning GitHub Actions to full-length commit SHAs.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch casper/feplat-5067-pin-github-actions

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

@socket-security

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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/ci.yml:
- Line 15: Update each checkout step in the pull_request workflow at the three
referenced locations to set persist-credentials to false, preventing
repository-controlled commands from accessing stored Git tokens. Preserve
credential persistence only in checkout steps that require authenticated Git
operations.

In @.github/workflows/publish.yml:
- Around line 123-126: Update the npm-logs artifact step using
actions/upload-artifact so files under ~/.npm/_logs/ are preserved after the
upgrade: either stage them in a non-hidden directory before upload or enable
include-hidden-files after validating the logs contain no secrets. Keep the
artifact named npm-logs and ensure it receives the generated npm logs.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fb8baec3-d148-4190-adca-1d8331af7378

📥 Commits

Reviewing files that changed from the base of the PR and between 4356441 and 5a3b9ed.

📒 Files selected for processing (3)
  • .github/actions/setup/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/publish.yml

Comment thread .github/workflows/ci.yml
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 8 'actions/checkout|persist-credentials|upload-artifact|git archive|tar|zip|\.git' .github/workflows/ci.yml
rg -n -C 6 'prepare|pack|archive|artifact' --glob 'package.json' --glob '*.yml' --glob '*.yaml' .

Repository: phantom/react-native-juicebox-sdk

Length of output: 2490


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- .github/workflows/ci.yml ---'
cat -n .github/workflows/ci.yml

printf '%s\n' '--- local setup action ---'
if [ -f .github/actions/setup/action.yml ]; then
  cat -n .github/actions/setup/action.yml
elif [ -f .github/actions/setup/action.yaml ]; then
  cat -n .github/actions/setup/action.yaml
fi

printf '%s\n' '--- workflow-related package and build configuration ---'
rg -n -C 5 'bob|files|prepare|publishConfig|artifact|upload-artifact|git|tar|zip|archive' \
  package.json bob.config.* .github/actions .github/workflows 2>/dev/null || true

printf '%s\n' '--- workflow expressions and credential references ---'
rg -n -C 4 'GITHUB_TOKEN|github.token|secrets\.|persist-credentials|checkout' \
  .github/workflows .github/actions 2>/dev/null || true

Repository: phantom/react-native-juicebox-sdk

Length of output: 15339


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import re

path = Path(".github/workflows/ci.yml")
lines = path.read_text().splitlines()

checkout_lines = [
    i for i, line in enumerate(lines)
    if re.search(r"\buses:\s*actions/checkout@", line)
]

print(f"checkout_count={len(checkout_lines)}")
for i in checkout_lines:
    end = len(lines)
    for j in range(i + 1, len(lines)):
        if re.match(r"\s+- name:", lines[j]) or re.match(r"\s+\w[\w-]*:", lines[j]):
            end = j
            break
    block = lines[i:end]
    has_opt_out = any("persist-credentials: false" in line for line in block)
    following_runs = [
        line.strip() for line in lines[i + 1:end]
        if re.search(r"\brun:\s*", line)
    ]
    print(
        f"line={i + 1} "
        f"persist_credentials_false={has_opt_out} "
        f"run_steps={following_runs}"
    )

text = path.read_text()
print(f"pull_request_trigger={'pull_request:' in text}")
print(f"explicit_permissions={'permissions:' in text}")
PY

Repository: phantom/react-native-juicebox-sdk

Length of output: 400


Sensitive Data Exposure (CWE-522): Insufficiently Protected Credentials

Reachability: External · Exploitability: Trivial

Disable credential persistence in the CI checkouts.

The pull_request workflow runs repository-controlled commands after each checkout. Without persist-credentials: false, those commands can read the token stored in local Git configuration. Add this option at lines 15, 30, and 42. Keep persistence only for workflows that require authenticated Git operations.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 14-15: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 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/ci.yml at line 15, Update each checkout step in the
pull_request workflow at the three referenced locations to set
persist-credentials to false, preventing repository-controlled commands from
accessing stored Git tokens. Preserve credential persistence only in checkout
steps that require authenticated Git operations.

Source: Linters/SAST tools

Comment on lines +123 to 126
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: npm-logs
path: ~/.npm/_logs/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
printf '%s\n' '--- workflow context ---'
sed -n '95,140p' .github/workflows/publish.yml
printf '%s\n' '--- npm log and artifact references ---'
rg -n -C 3 'upload-artifact|npm-logs|npm/_logs|include-hidden-files|npm config|NPM_CONFIG' .github package.json package-lock.json 2>/dev/null || true

Repository: phantom/react-native-juicebox-sdk

Length of output: 2352


🌐 Web query:

actions/upload-artifact include-hidden-files hidden files hidden directories default behavior v7.0.1

💡 Result:

In actions/upload-artifact version 7.0.1, the default behavior regarding hidden files is that they are excluded from the upload [1][2][3]. To improve security and prevent the accidental exposure of sensitive information (such as credentials), the action ignores hidden files and directories by default [1][4][5]. A hidden file is defined as any file starting with a dot (.) or any file located within a directory that starts with a dot [4][6]. On Windows, files and directories with the hidden attribute are only considered hidden by this action if they also have the leading dot prefix [6]. If your workflow requires uploading hidden files, you must explicitly enable them by setting the include-hidden-files input to true [1][7][3]: - uses: actions/upload-artifact@v7 with: name: my-artifact include-hidden-files: true path: path/to/your/files/ This default exclusion behavior was introduced as a breaking change in v4.4.0 [8][9] and remains the standard for all subsequent versions, including v7.0.1 [1][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import json
import pathlib
import urllib.request

repo = "actions/upload-artifact"
tag = "v7.0.1"
pin = "043fb46d1a93c77aae656e7c1c64a875d1fc6a0a"

def get(url):
    req = urllib.request.Request(url, headers={"User-Agent": "read-only-review-check"})
    with urllib.request.urlopen(req, timeout=20) as response:
        return json.load(response)

ref = get(f"https://api.github.com/repos/{repo}/git/ref/tags/{tag}")["object"]
if ref["type"] == "tag":
    target = get(f"https://api.github.com/repos/{repo}/git/tags/{ref['sha']}")["object"]
else:
    target = ref
tag_commit = target["sha"]
pin_commit = get(f"https://api.github.com/repos/{repo}/commits/{pin}")["sha"]

readme_url = f"https://raw.githubusercontent.com/{repo}/{tag}/README.md"
req = urllib.request.Request(readme_url, headers={"User-Agent": "read-only-review-check"})
with urllib.request.urlopen(req, timeout=20) as response:
    readme = response.read().decode()

path = pathlib.PurePosixPath("~/.npm/_logs/")
components = [part for part in path.parts if part not in (".", "..", "/", "~")]
hidden_components = [part for part in components if part.startswith(".")]

print(f"tag_commit={tag_commit}")
print(f"pin_commit={pin_commit}")
print(f"pin_matches_tag={pin_commit == tag_commit}")
print(f"path_components={components}")
print(f"hidden_components={hidden_components}")
print("readme_mentions_include_hidden_files_true=" +
      str("include-hidden-files: true" in readme))
for line in readme.splitlines():
    if "hidden" in line.lower() and ("exclude" in line.lower() or "include-hidden-files" in line):
        print(line.strip())
PY

Repository: phantom/react-native-juicebox-sdk

Length of output: 2492


Preserve npm logs after the artifact action upgrade.

actions/upload-artifact excludes files in hidden directories by default. The ~/.npm/_logs/ path can therefore produce an empty artifact. Stage the logs in a non-hidden directory, or set include-hidden-files: true after validating that the logs contain no secrets.

🤖 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/publish.yml around lines 123 - 126, Update the npm-logs
artifact step using actions/upload-artifact so files under ~/.npm/_logs/ are
preserved after the upgrade: either stage them in a non-hidden directory before
upload or enable include-hidden-files after validating the logs contain no
secrets. Keep the artifact named npm-logs and ensure it receives the generated
npm logs.

@casper-phantom

casper-phantom Bot commented Aug 5, 2026

Copy link
Copy Markdown
Author

Closing at the requester's direction: this is a public repository, so the work is being pulled back. No changes were merged.

@casper-phantom casper-phantom Bot closed this Aug 5, 2026
@casper-phantom
casper-phantom Bot deleted the casper/feplat-5067-pin-github-actions branch August 5, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant