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
29 changes: 27 additions & 2 deletions .github/workflows/build-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -353,14 +353,24 @@ jobs:
done
rm -f "$RUNNER_TEMP/notary_key.p8"

- name: Tag & publish GitHub Release
- name: Tag GitHub Release & upload assets (draft)
# Immutable releases (now enabled on this repo) freeze a Release's
# assets the moment it is *published*, so every asset must be attached
# while the release is still a draft. Create it as a draft here (drafts
# stay mutable), upload all four artifacts, then publish it in the next
# step. Doing it published-in-one-shot fails with "Cannot upload asset
# ... to an immutable release" partway through the upload — softprops'
# own hint is exactly this: "keep the release as a draft with
# draft: true, then publish it later from that draft."
uses: softprops/action-gh-release@v3

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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify all workflow `uses:` references are pinned to full commit SHAs.
# Expected: third-party actions should use @<40-hex-sha>, not `@vN` tags.
rg -n '^\s*uses:\s*[^@]+@' .github/workflows \
| awk '
{
  ref=$0
  if (ref ~ /@[0-9a-fA-F]{40}\s*$/) status="PINNED"
  else status="UNPINNED"
  print status " :: " ref
}'

Repository: oomol-lab/LockIME

Length of output: 530


🏁 Script executed:

sed -n '360,370p' .github/workflows/build-publish.yml | cat -n

Repository: oomol-lab/LockIME

Length of output: 933


Pin the release action to an immutable commit SHA.

Line 365 uses softprops/action-gh-release@v3, which is mutable and currently violates your workflow policy gate (unpinned-uses). Please pin to a full commit SHA to harden the supply chain and keep CI policy-compliant.

🧰 Tools
🪛 zizmor (1.26.1)

[error] 365-365: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[info] 365-365: action functionality is already included by the runner (superfluous-actions): use gh release in a script step

(superfluous-actions)

🤖 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-publish.yml at line 365, The
softprops/action-gh-release action on line 365 is pinned to a mutable version
tag `@v3` instead of an immutable commit SHA, which violates the workflow policy
gate. Replace the version tag `@v3` with a full commit SHA (e.g.,
`@abc123def456`...) to ensure the action is pinned to a specific immutable commit.
You can find the appropriate commit SHA by checking the releases or commits of
the softprops/action-gh-release repository on GitHub.

Source: Linters/SAST tools

with:
tag_name: ${{ inputs.tag }}
# Pin the tag to the commit that was actually built, not whatever
# the default branch points at by the time this step runs.
# the default branch points at by the time this step runs. The tag
# ref itself is only created when the draft is published (next step).
target_commitish: ${{ github.sha }}
prerelease: ${{ inputs.prerelease }}
draft: true
# Four artifacts per release: a zip (the Sparkle enclosure) and a
# dmg (manual download) for each architecture. The dist dirs also
# hold .md release notes and the appcast — only the zips ship.
Expand All @@ -374,6 +384,21 @@ jobs:
# independently and only populate the Release page, not the appcast.)
body_path: build/release-notes.md

- name: Publish GitHub Release
# Flip the draft to published now that all assets are attached. This is
# where the tag (on github.sha, recorded above) is created and the
# release becomes immutable — with its assets already in place.
# --draft=false touches only the draft flag, so prerelease is preserved
# (a beta stays a pre-release and never becomes "Latest"; GitHub still
# auto-computes "Latest" for stable on publish, same as before). The
# downstream steps below run sequentially in this same job and don't
# subscribe to release.published/release.prereleased events, so the
# draft-publishes-as-release.published quirk doesn't affect them.
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ inputs.tag }}
run: gh release edit "$TAG" --draft=false

- name: Stage appcasts for gh-pages
# Publish ONLY the appcasts. The dist dirs also hold the distribution
# zips, which the appcasts never reference (enclosure URLs point at
Expand Down
Loading