Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,40 @@ jobs:
github.event_name == 'workflow_dispatch' ||
github.event.pull_request.merged == true
runs-on: ubuntu-latest
outputs:
tag_name: ${{ steps.drafter.outputs.tag_name }}
steps:
- uses: release-drafter/release-drafter@v6
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the release.yml file to understand the full context
cd .github/workflows 2>/dev/null && ls -la release.yml 2>/dev/null || find . -name "release.yml" -type f

Repository: bd73-com/fetchthechange

Length of output: 127


🏁 Script executed:

# Search for the release.yml file from the repo root
find . -name "release.yml" -type f

Repository: bd73-com/fetchthechange

Length of output: 98


🏁 Script executed:

# Once located, examine the file content
git ls-files | grep -E "\.github.*release\.yml"

Repository: bd73-com/fetchthechange

Length of output: 96


🏁 Script executed:

# Read the release.yml file to see the current state
cat -n .github/workflows/release.yml

Repository: bd73-com/fetchthechange

Length of output: 1871


🏁 Script executed:

# Now let's research current best practices for GitHub Actions pinning
# Check if there's any documentation or standard guidance in the repo
find . -name "*.md" -type f | head -20 | xargs grep -l "GitHub Actions\|actions/checkout\|security" 2>/dev/null | head -5

Repository: bd73-com/fetchthechange

Length of output: 228


🌐 Web query:

GitHub Actions pinning commit SHA security best practices 2024 2025

💡 Result:

GitHub Actions: commit-SHA pinning security best practices (2024–2025)

  • Pin all third‑party actions to a full‑length commit SHA (not @v1, @main, or other movable tags/branches). This is GitHub’s recommended way to consume an action immutably and reduces supply‑chain risk from tag retargeting or repo compromise. [1][2]

    • Example: uses: actions/checkout@<40-hex-sha>
  • Pin reusable workflows too (uses: org/repo/.github/workflows/workflow.yml@<sha>), for the same “immutable dependency” reason. [2]

  • Prefer “immutable releases,” but treat tags as mutable in practice: GitHub’s guidance emphasizes commit SHAs as the reliable immutable reference for third‑party actions. [2]

  • Enforce SHA pinning with policy where possible: GitHub Actions policy can be configured to require full commit SHAs (workflows that reference unpinned actions can be blocked/fail), which helps scale the practice across orgs/enterprises. [3]

  • Automate verification in CI: Add a check that fails PRs if any uses: reference isn’t a full SHA (e.g., “Ensure SHA Pinned Actions” / similar linters). [4]

  • Operationalize updates safely: Because SHA pinning trades “auto-updates” for immutability, use an updater process (e.g., Dependabot for GitHub Actions updates, plus review/testing) to regularly advance pinned SHAs. (GitHub’s security hardening guidance is the basis for this workflow.) [2]

Sources: GitHub Docs security hardening guidance [2], GitHub Well‑Architected Actions security recommendations [1], GitHub Changelog for SHA‑pinning enforcement policy [3], and an example enforcement action [4].


🌐 Web query:

release-drafter GitHub Actions v6 tag pinning supply chain risk

💡 Result:

Using release-drafter/release-drafter@v6 is a floating (mutable) major tag. If the tag is moved (accidentally, maliciously, or after a maintainer compromise), your workflow will silently start running different code—this is a classic GitHub Actions supply-chain risk. The official Marketplace example still shows @v6 usage, which is convenient but not immutable. [1]

What to do instead (recommended)

Pin to a full commit SHA (immutable), optionally keeping the human-readable version in a comment:

- uses: release-drafter/release-drafter@<full_commit_sha> # v6

GitHub explicitly recommends pinning actions to a specific commit SHA to reduce the impact of a compromised dependency. [2] OpenSSF guidance similarly notes SHA pinning prevents “tag renaming/retargeting” style attacks. [3]

Operationalizing it (so it stays updated)

  • Use an automated tool/workflow to convert mutable tags to SHAs (and keep them updated), e.g., StepSecurity’s tooling that pins action tags to full SHAs. [4]
  • If you’re on GitHub Enterprise / have the feature available, GitHub Actions policy can support/enforce SHA pinning at the org/enterprise level. [2]

Bottom line: @v6 is normal but not tamper-resistant; pin release-drafter to a full commit SHA to materially reduce supply-chain risk. [2][3]

References:
[1] Release Drafter – GitHub Marketplace (example shows release-drafter/release-drafter@v6) (github.com)
[2] GitHub Changelog – Actions policy supports blocking and SHA pinning; GitHub recommends pinning to commit SHA (github.blog)
[3] OpenSSF – Mitigating Attack Vectors in GitHub Workflows (SHA pinning reduces tag-retargeting risk) (openssf.org)
[4] StepSecurity secure-repo – notes action tags are mutable; automates pinning to full SHAs (github.com)

Citations:


Pin GitHub Actions to immutable commit SHAs to reduce supply-chain attack surface.

Using floating tags (@v6, @v4, etc.) creates a mutable dependency that could execute different code if the tag is retargeted—either through maintainer compromise, accident, or malicious activity. GitHub's security hardening guidance and OpenSSF recommendations explicitly advise pinning all third-party actions to their full commit SHA.

Update the following:

  • Line 23: release-drafter/release-drafter@v6 → pin to commit SHA
  • Line 36: actions/checkout@v4 → pin to commit SHA
  • Line 38: actions/setup-node@v4 → pin to commit SHA

Consider automating SHA updates via Dependabot or similar tooling to keep pinned dependencies current without sacrificing immutability.

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

In @.github/workflows/release.yml at line 23, Replace floating action tags with
immutable commit SHAs: update the occurrences of
release-drafter/release-drafter@v6, actions/checkout@v4, and
actions/setup-node@v4 to their respective full commit SHAs (e.g.,
release-drafter/release-drafter@<commit-sha>, actions/checkout@<commit-sha>,
actions/setup-node@<commit-sha>), by looking up the latest trusted commit in
each action's GitHub repository and substituting the tag; optionally configure
Dependabot to keep these SHAs up to date automatically.

id: drafter
with:
publish: true
config-name: release-drafter.yml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

upload-extension:
needs: update-release-draft
if: needs.update-release-draft.outputs.tag_name
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

Comment on lines +31 to +37
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/release.yml | head -60

Repository: bd73-com/fetchthechange

Length of output: 1871


🏁 Script executed:

# Get the full upload-extension job to see what it does
rg -A 30 "upload-extension:" .github/workflows/release.yml

Repository: bd73-com/fetchthechange

Length of output: 853


🏁 Script executed:

rg "run:|node|npm|yarn" .github/workflows/release.yml | head -20

Repository: bd73-com/fetchthechange

Length of output: 247


Disable credential persistence and restrict job permissions before executing repository build scripts.

The upload-extension job checks out the repository with actions/checkout@v4 (which persists Git credentials by default) and then executes repository-controlled Node scripts (scripts/build.js and scripts/package.js). If these scripts are compromised, they gain access to the persisted credentials. Disable credential persistence and apply least-privilege job-level permissions.

🛡️ Proposed least-privilege adjustment
   upload-extension:
     needs: update-release-draft
     if: needs.update-release-draft.outputs.tag_name
     runs-on: ubuntu-latest
+    permissions:
+      contents: write
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v4
+        with:
+          persist-credentials: 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.

Suggested change
upload-extension:
needs: update-release-draft
if: needs.update-release-draft.outputs.tag_name
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
upload-extension:
needs: update-release-draft
if: needs.update-release-draft.outputs.tag_name
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 31 - 37, The upload-extension job
should disable credential persistence and limit job permissions: update the
actions/checkout@v4 step in the upload-extension job to set persist-credentials:
false so repository Git credentials are not stored for downstream scripts, and
add a job-level permissions block (e.g., permissions: contents: read) to enforce
least privilege for running repository-controlled scripts like scripts/build.js
and scripts/package.js; ensure the changes target the upload-extension job and
the checkout step.

- uses: actions/setup-node@v4
with:
node-version: 20

- name: Install dependencies
run: npm ci
working-directory: extension

- name: Build and package extension
run: NODE_ENV=production node scripts/build.js && node scripts/package.js
working-directory: extension
Comment on lines +46 to +48
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Use the existing npm script to avoid command drift.

Call npm run package so workflow behavior stays aligned with extension/package.json scripts.

♻️ Proposed refactor
       - name: Build and package extension
-        run: NODE_ENV=production node scripts/build.js && node scripts/package.js
+        run: npm run package
         working-directory: extension
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 46 - 48, Replace the hardcoded
build/package commands in the GitHub Actions job (the step currently named
"Build and package extension" that runs "NODE_ENV=production node
scripts/build.js && node scripts/package.js" in the extension working-directory)
with the npm script defined in extension/package.json by invoking "npm run
package" (ensuring NODE_ENV is preserved if needed); update the step to use the
npm run package invocation so the workflow follows the package script in
package.json rather than calling scripts/build.js and scripts/package.js
directly.


- name: Upload extension zip to release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: >-
gh release upload "${{ needs.update-release-draft.outputs.tag_name }}"
extension/fetchthechange-extension.zip
--clobber
Loading