Thanks to visit codestin.com
Credit goes to github.com

Skip to content

ci security#1612

Open
daniel-noland wants to merge 10 commits into
mainfrom
pr/daniel-noland/ci-security
Open

ci security#1612
daniel-noland wants to merge 10 commits into
mainfrom
pr/daniel-noland/ci-security

Conversation

@daniel-noland

Copy link
Copy Markdown
Collaborator

Spruce up CI security in response to more opengrep findings.

Specifically, opengrep now wants pinned github actions.

I added pinact to manage the pinning and zizmor to address other security issues in the CI while we are at it.

@daniel-noland daniel-noland self-assigned this Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds lint tooling and configuration, rewires lint execution through just and dev.yml, pins multiple GitHub Actions to commit SHAs, tightens workflow permissions, and updates bump/dependency automation workflows and recipes.

Changes

Tooling and workflow updates

Layer / File(s) Summary
Lint configs and shell tools
.commitlintrc.yaml, .github/zizmor.yml, .pinact.yaml, default.nix
Adds commitlint, pinact, and zizmor configuration files and installs the matching tools into the dev shell.
Lint recipes and workflow wiring
justfile, .github/workflows/README.md, .github/workflows/dev.yml
Adds lint-related just recipes, replaces the top-level lint recipe with a fixed check sequence, updates the workflow README, and adds the new lint job and summary gating in dev.yml.
Pinned actions and validators
.github/actions/nix-setup/action.yml, .github/actions/nix-shell/action.yml, .github/workflows/fossa.yml, .github/workflows/lint-commitlint.yml, .github/workflows/lint-validate-dependabot.yml, .github/workflows/mergeability.yml
Pins reusable actions and workflow validators to commit SHAs, and adds concurrency controls for validation workflows.
Dev workflow hardening
.github/workflows/dev.yml
Pins and rewires the main development workflow jobs, narrows permissions, changes the Rust lint step to clippy, and adjusts build, cross, and publish job wiring.
Bump automation
.github/workflows/bump.yml, .github/workflows/version-bump.yml, .github/dependabot.yml, justfile
Updates Dependabot cooldown settings, tightens bump workflow permissions, pins bump workflow actions, and adds the just automation used for action and cargo dependency upgrades.

Related Issues: None mentioned.

Related PRs: None mentioned.

Suggested labels: ci, tooling, github-actions

Suggested reviewers: None specified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is related to the changes, but it is too vague to describe the specific CI security updates. Use a more specific title, such as pinning GitHub Actions and adding CI security linting tools.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description matches the changes and explains the CI pinning and security tooling updates.
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.

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.

❤️ Share

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

@daniel-noland daniel-noland added dependencies Pull requests that update a dependency file ci Continuous Integration clean-up Code base clean-up, no functional change ci:+vlab Enable VLAB tests ci:+cross/full labels Jul 1, 2026
@daniel-noland daniel-noland requested a review from Copilot July 1, 2026 03:00

Copilot AI left a comment

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.

Pull request overview

This PR strengthens CI supply-chain and permissions posture by pinning GitHub Actions to commit SHAs, introducing automated enforcement (pinact) and workflow security linting (zizmor), and tightening workflow permissions/concurrency settings.

Changes:

  • Pin all uses: GitHub Actions/reusable workflow references to commit SHAs (with version comments) and add a lint-pinact workflow to enforce this.
  • Add zizmor (and a lint-zizmor workflow) plus new just recipes to run CI security tooling locally/consistently.
  • Reduce default workflow permissions and add targeted permissions/comments where elevated access is required.

Reviewed changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
justfile Adds opengrep, pinact, zizmor, and updates lint aggregation.
default.nix Adds pinact and zizmor to the dev shell toolset.
Cargo.lock Updates a few Rust dependencies (lockfile churn from upgrades).
.pinact.yaml Configures pinact rules (currently with an ignore exception).
.github/zizmor.yml Introduces zizmor configuration file placeholder.
.github/workflows/version-bump.yml Pins actions + scopes permissions via GitHub App token.
.github/workflows/README.md Updates documented lint command to just clippy.
.github/workflows/mergeability.yml Adds concurrency settings for merge queue behavior.
.github/workflows/lint-zizmor.yml New workflow to run zizmor in CI.
.github/workflows/lint-validate-dependabot.yml Pins actions + adds concurrency and job naming.
.github/workflows/lint-pinact.yml New workflow to enforce pinned action refs/version comments.
.github/workflows/lint-opengrep.yml Pins checkout action and delegates to just opengrep.
.github/workflows/lint-license-headers.yml Pins checkout action.
.github/workflows/lint-commitlint.yml Pins checkout + commitlint action and improves naming.
.github/workflows/lint-cargo-fmt.yml Pins checkout action.
.github/workflows/lint-actionlint.yml Pins checkout action.
.github/workflows/fossa.yml Pins checkout + fossa action and adjusts checkout creds.
.github/workflows/dev.yml Pins actions, tightens permissions, and adjusts lint step naming/recipe.
.github/workflows/bump.yml Pins actions + scopes permissions via GitHub App token (but currently incomplete).
.github/actions/nix-shell/action.yml Pins composite action dependencies (nix/cachix/use-nix-shell).
.github/actions/nix-setup/action.yml Pins docker/login-action used by the composite action.

Comment thread justfile Outdated
Comment thread justfile Outdated
Comment thread .github/workflows/bump.yml Outdated
Comment thread .pinact.yaml
@daniel-noland daniel-noland force-pushed the pr/daniel-noland/ci-security branch 4 times, most recently from 202433a to 9775945 Compare July 1, 2026 05:56
@daniel-noland daniel-noland marked this pull request as ready for review July 1, 2026 06:31
@daniel-noland daniel-noland requested a review from a team as a code owner July 1, 2026 06:31
@daniel-noland daniel-noland requested review from Copilot and qmonnet and removed request for a team July 1, 2026 06:31

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 19 out of 20 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/dev.yml
Comment on lines +200 to +205
if: >-
${{
needs.check_changes.outputs.devfiles == 'true'
|| startsWith(github.event.ref, 'refs/tags/v')
|| github.event_name == 'workflow_dispatch'
}}

@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

🧹 Nitpick comments (1)
.github/workflows/lint-validate-dependabot.yml (1)

9-12: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Verify concurrency group is well-formed for all trigger types.

The group key ${{ github.workflow }}:${{ github.event.pull_request.number }} relies on pull_request.number, which is only populated for pull_request-triggered events. If this workflow also runs on other event types (e.g., push, merge_group), the group key would contain a literal empty/null segment, which is harmless but slightly imprecise (multiple non-PR runs could collide into the same group and cancel each other).

Fallback suggestion
 concurrency:
-  group: "${{ github.workflow }}:${{ github.event.pull_request.number }}"
+  group: "${{ github.workflow }}:${{ github.event.pull_request.number || github.ref }}"
   cancel-in-progress: true
🤖 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/lint-validate-dependabot.yml around lines 9 - 12, The
concurrency group in the workflow is too specific to pull_request events because
it uses github.event.pull_request.number, which may be empty for other triggers.
Update the concurrency.group expression to use a fallback that is always
populated for all event types, and keep the identifier stable per run source by
referencing github.workflow together with a safe event-based key in the
lint-validate-dependabot workflow. This will prevent unrelated push or
merge_group runs from collapsing into the same concurrency bucket.
🤖 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 @.commitlintrc.yaml:
- Around line 24-29: The commitlint-rs config is using unsupported rule keys in
the message description section, so these checks will not run. Update the rule
names in .commitlintrc.yaml from description-format and description-max-length
to the commitlint-rs-supported subject-related keys, keeping the same format and
length constraints. Use the existing rule block in the config as the place to
swap the names while preserving their level and validation values.

In @.github/workflows/dev.yml:
- Line 69: The workflow pin for dorny/paths-filter is inconsistent with its
version comment, so update the uses reference to the correct release SHA or
adjust the comment to match the pinned version. Locate the existing pinned
action entry in dev.yml alongside the other workflow steps and make the
version/tag and commit hash agree.

---

Nitpick comments:
In @.github/workflows/lint-validate-dependabot.yml:
- Around line 9-12: The concurrency group in the workflow is too specific to
pull_request events because it uses github.event.pull_request.number, which may
be empty for other triggers. Update the concurrency.group expression to use a
fallback that is always populated for all event types, and keep the identifier
stable per run source by referencing github.workflow together with a safe
event-based key in the lint-validate-dependabot workflow. This will prevent
unrelated push or merge_group runs from collapsing into the same concurrency
bucket.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 87ab51c6-e041-429b-94f6-133e45830a3e

📥 Commits

Reviewing files that changed from the base of the PR and between 70f9521 and 9775945.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (19)
  • .commitlintrc.yaml
  • .github/actions/nix-setup/action.yml
  • .github/actions/nix-shell/action.yml
  • .github/workflows/README.md
  • .github/workflows/bump.yml
  • .github/workflows/dev.yml
  • .github/workflows/fossa.yml
  • .github/workflows/lint-actionlint.yml
  • .github/workflows/lint-cargo-fmt.yml
  • .github/workflows/lint-commitlint.yml
  • .github/workflows/lint-license-headers.yml
  • .github/workflows/lint-opengrep.yml
  • .github/workflows/lint-validate-dependabot.yml
  • .github/workflows/mergeability.yml
  • .github/workflows/version-bump.yml
  • .github/zizmor.yml
  • .pinact.yaml
  • default.nix
  • justfile
💤 Files with no reviewable changes (4)
  • .github/workflows/lint-actionlint.yml
  • .github/workflows/lint-cargo-fmt.yml
  • .github/workflows/lint-opengrep.yml
  • .github/workflows/lint-license-headers.yml

Comment thread .commitlintrc.yaml
Comment on lines +24 to +29
description-format:
level: error
format: "^.*[^.]$"
description-max-length:
level: error
length: 72

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

🌐 Web query:

What rules does commitlint-rs (KeisukeYamashita/commitlint-rs) support, specifically description-format and description-max-length?

💡 Result:

The commitlint-rs project (KeisukeYamashita/commitlint-rs) does not natively support rules named description-format or description-max-length [1][2][3]. In the context of commitlint-rs, the commit message header is typically referred to as the subject [1][4]. While the tool supports various configuration rules for subject and body validation, these specific identifiers (description-format and description-max-length) are not part of its standard rule set [1][3][4]. Users commonly confuse commitlint-rs with other tools like cargo-commitlint (which is a separate project) or the Node-based commitlint [4][5]. For example, cargo-commitlint provides rules such as header-max-length and subject-case, but does not use the specific names you queried [4][5]. If you are looking to enforce length or format constraints on the commit subject in commitlint-rs, you should consult the project's official rule documentation [3], which details the rules currently implemented in the library. As of the latest available information, there is no evidence of "description" being used as a rule prefix in this tool [1][3].

Citations:


Use commitlint-rs rule names here

description-format and description-max-length are not recognized by commitlint-rs, so these checks won’t run. Rename them to the supported rule keys for the message part you want to validate.

🤖 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 @.commitlintrc.yaml around lines 24 - 29, The commitlint-rs config is using
unsupported rule keys in the message description section, so these checks will
not run. Update the rule names in .commitlintrc.yaml from description-format and
description-max-length to the commitlint-rs-supported subject-related keys,
keeping the same format and length constraints. Use the existing rule block in
the config as the place to swap the names while preserving their level and
validation values.

Comment thread .github/workflows/dev.yml

@qmonnet qmonnet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good overall (with minor comments inline below).

My main concern is the pinning of the GitHub Actions versions. I understand why it makes it better reproducible to pin the Actions, although I don't think we've been bitten by sliding tags so far, so is this something you want to do to harden the posture, or is it to make opengrep happy?

The thing that worries me is that, unless I'm mistaken, Dependabot will start opening PRs to update Actions hashes for every single patch release, and it's going to be rather noisy (and annoying). Do we have a way to limit that? If we could have all Dependabot non-urgent updates in a single, weekly PR, for example, it would be nice, but I don't know if it supports this.

packages: "read"
id-token: "write"
pull-requests: "write"
contents: "read" # actions/checkout on this private repo; git push + PR go through the scoped app token below

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not sure I understand the comment, what “private” repo are we talking about? (Same question in dev.yml)


jobs:
format-check:
name: "Check formatting for Rust code"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This one seems to be removed rather than moved, this is because we already run it in the check job for dev.yml, right?

Comment thread .github/workflows/dev.yml
with:
recipe: "check-dependencies"

- name: "commitlint"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand the motivation for this new lint. But from the commit description, I understand you plan to discuss it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Discussed during the meeting - this is to make it easier to run the linter locally from the nix-shell, without pulling the Node.js ecosystem.

Should ideally be mentioned in the commit log.

@daniel-noland daniel-noland force-pushed the pr/daniel-noland/ci-security branch 2 times, most recently from b71cd37 to 2dcd76b Compare July 1, 2026 21:19

@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: 5

🤖 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/bump-actions.yml:
- Around line 47-69: Run the pin update step before the Create Pull Request step
in the workflow so scheduled runs actually generate action pin changes; add the
missing bump step using the existing nix-shell setup path and make sure it
produces the changes that `create-pull-request` will commit. Also fix the PR
body reference by replacing the nonexistent `steps.upgrade.outputs.upgrade` with
the output from the newly added bump step, keeping the workflow aligned with the
`nix-shell` and `Create Pull Request` steps.

In @.github/workflows/bump.yml:
- Around line 79-82: The workflow step renamed to `cargo update` no longer
provides the `upgrade` step output, but later references still read
`steps.upgrade.outputs.upgrade`. Update the workflow so the `just`-driven step
(`bump-cargo-deps`) either exposes a matching output via an explicit `id:
upgrade`/composite-action output contract, or change the downstream PR body
generation to use static text instead of `steps.upgrade.outputs.upgrade`.

In `@justfile`:
- Around line 526-545: The PR summary/output is currently only written when
`nb_upgrades` is at least 1, so lockfile-only changes leave `upgrade_log` empty;
update the summary generation logic around the `nb_upgrades` check to include a
fallback message for lockfile-only updates. Keep the existing
`upgrade_log`/`GITHUB_STEP_SUMMARY`/`GITHUB_OUTPUT` flow in `justfile`, but add
a branch that writes a short summary when `cargo update` changed files without
any package upgrades, so the generated PR always has content.
- Around line 510-511: The staging step in the justfile is too narrow because it
only adds Cargo.lock, Cargo.toml, and cli/Cargo.toml, which can miss other
modified workspace manifests. Update the commit staging command to include all
relevant Cargo manifest files in the workspace, using the existing justfile
commit flow around the git add and git commit steps so upgrades in any workspace
member are captured.
- Around line 495-512: The upgrade loop is consuming non-package lines from the
`cargo upgrade --dry-run` output, which can cause invalid values to be passed
into `cargo upgrade --package`. Update the filtering step in the `justfile`
workflow so only actual table rows/package names are written to `list_packages`,
using the upgrade script’s existing output-processing block around `cargo
upgrade --dry-run`, `sed`, and the `while read -r package` loop.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 67766e3a-771e-429d-9014-685e963257c8

📥 Commits

Reviewing files that changed from the base of the PR and between 9c60c11 and 2dcd76b.

📒 Files selected for processing (7)
  • .github/dependabot.yml
  • .github/workflows/bump-actions.yml
  • .github/workflows/bump.yml
  • .github/workflows/dev.yml
  • .github/zizmor.yml
  • .pinact.yaml
  • justfile
✅ Files skipped from review due to trivial changes (2)
  • .github/zizmor.yml
  • .pinact.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/dev.yml

Comment thread .github/workflows/bump-actions.yml Outdated
Comment thread .github/workflows/bump.yml Outdated
Comment on lines +79 to +82
- name: "cargo update"
uses: *just
with:
recipe: "bump-cargo-deps"

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

Preserve or remove the stale upgrade output contract.

The new cargo update step no longer defines id: upgrade, but the PR body still reads steps.upgrade.outputs.upgrade later in the workflow. Either expose a real output from the recipe/composite action or replace the body with static text.

Minimal fallback fix
           sign-commits: "true"
           body: |
-            ${{ steps.upgrade.outputs.upgrade }}
+            Automated dependency update generated by `just bump-cargo-deps`.
🤖 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/bump.yml around lines 79 - 82, The workflow step renamed
to `cargo update` no longer provides the `upgrade` step output, but later
references still read `steps.upgrade.outputs.upgrade`. Update the workflow so
the `just`-driven step (`bump-cargo-deps`) either exposes a matching output via
an explicit `id: upgrade`/composite-action output contract, or change the
downstream PR body generation to use static text instead of
`steps.upgrade.outputs.upgrade`.

Comment thread justfile
Comment thread justfile
Comment on lines +510 to +511
git add Cargo.lock Cargo.toml cli/Cargo.toml
git commit -sF "${commit_msg}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Stage all modified Cargo manifests.

Hard-coding cli/Cargo.toml drops upgrades made in any other workspace manifest.

Proposed staging fix
-        git add Cargo.lock Cargo.toml cli/Cargo.toml
+        git ls-files -z -- Cargo.lock ':(glob)**/Cargo.toml' | xargs -0 git add --
         git commit -sF "${commit_msg}"
📝 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
git add Cargo.lock Cargo.toml cli/Cargo.toml
git commit -sF "${commit_msg}"
git ls-files -z -- Cargo.lock ':(glob)**/Cargo.toml' | xargs -0 git add --
git commit -sF "${commit_msg}"
🤖 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 `@justfile` around lines 510 - 511, The staging step in the justfile is too
narrow because it only adds Cargo.lock, Cargo.toml, and cli/Cargo.toml, which
can miss other modified workspace manifests. Update the commit staging command
to include all relevant Cargo manifest files in the workspace, using the
existing justfile commit flow around the git add and git commit steps so
upgrades in any workspace member are captured.

Comment thread justfile
Comment on lines +526 to +545
if [[ "${nb_upgrades}" -ge 1 ]]; then
{
echo "### :rocket: Upgrades available";
echo ""
echo "| name | old | req | compatible | latest |";
echo "|------|-----|-----|------------|--------|";
awk '{print "| " $1 " | " $2 " | " $3 " | " $4 " | " $5 " |"}' < <(sed 1,2d < "${upgrade_output}");
echo ""
echo ":warning: This Pull Request was automatically generated and should be carefully reviewed before acceptance. It may introduce **breaking changes**."
echo ""
} > "${upgrade_log}"
fi

if [ -n "${GITHUB_STEP_SUMMARY:-}" ] && [ -n "${GITHUB_OUTPUT:-}" ] && [ -w "${GITHUB_STEP_SUMMARY}" ] && [ -w "${GITHUB_OUTPUT}" ]; then
cat "${upgrade_log}" > "${GITHUB_STEP_SUMMARY}"
{
echo "upgrade<<EOF";
cat "${upgrade_log}";
echo "EOF";
} >> "${GITHUB_OUTPUT}"

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

Add a summary for lockfile-only updates.

If only cargo update commits changes, nb_upgrades is 0, so the generated PR summary/output is empty.

Proposed fallback
     if [[ "${nb_upgrades}" -ge 1 ]]; then
         {
             echo "### :rocket: Upgrades available";
@@
             echo ""
         } > "${upgrade_log}"
+    else
+        {
+            echo "### :package: Lockfile update";
+            echo "";
+            echo "This Pull Request contains dependency resolution updates from \`cargo update\`.";
+            echo "";
+        } > "${upgrade_log}"
     fi
📝 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
if [[ "${nb_upgrades}" -ge 1 ]]; then
{
echo "### :rocket: Upgrades available";
echo ""
echo "| name | old | req | compatible | latest |";
echo "|------|-----|-----|------------|--------|";
awk '{print "| " $1 " | " $2 " | " $3 " | " $4 " | " $5 " |"}' < <(sed 1,2d < "${upgrade_output}");
echo ""
echo ":warning: This Pull Request was automatically generated and should be carefully reviewed before acceptance. It may introduce **breaking changes**."
echo ""
} > "${upgrade_log}"
fi
if [ -n "${GITHUB_STEP_SUMMARY:-}" ] && [ -n "${GITHUB_OUTPUT:-}" ] && [ -w "${GITHUB_STEP_SUMMARY}" ] && [ -w "${GITHUB_OUTPUT}" ]; then
cat "${upgrade_log}" > "${GITHUB_STEP_SUMMARY}"
{
echo "upgrade<<EOF";
cat "${upgrade_log}";
echo "EOF";
} >> "${GITHUB_OUTPUT}"
if [[ "${nb_upgrades}" -ge 1 ]]; then
{
echo "### :rocket: Upgrades available";
echo ""
echo "| name | old | req | compatible | latest |";
echo "|------|-----|-----|------------|--------|";
awk '{print "| " $1 " | " $2 " | " $3 " | " $4 " | " $5 " |"}' < <(sed 1,2d < "${upgrade_output}");
echo ""
echo ":warning: This Pull Request was automatically generated and should be carefully reviewed before acceptance. It may introduce **breaking changes**."
echo ""
} > "${upgrade_log}"
else
{
echo "### :package: Lockfile update";
echo "";
echo "This Pull Request contains dependency resolution updates from \`cargo update\`.";
echo "";
} > "${upgrade_log}"
fi
if [ -n "${GITHUB_STEP_SUMMARY:-}" ] && [ -n "${GITHUB_OUTPUT:-}" ] && [ -w "${GITHUB_STEP_SUMMARY}" ] && [ -w "${GITHUB_OUTPUT}" ]; then
cat "${upgrade_log}" > "${GITHUB_STEP_SUMMARY}"
{
echo "upgrade<<EOF";
cat "${upgrade_log}";
echo "EOF";
} >> "${GITHUB_OUTPUT}"
🤖 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 `@justfile` around lines 526 - 545, The PR summary/output is currently only
written when `nb_upgrades` is at least 1, so lockfile-only changes leave
`upgrade_log` empty; update the summary generation logic around the
`nb_upgrades` check to include a fallback message for lockfile-only updates.
Keep the existing `upgrade_log`/`GITHUB_STEP_SUMMARY`/`GITHUB_OUTPUT` flow in
`justfile`, but add a branch that writes a short summary when `cargo update`
changed files without any package upgrades, so the generated PR always has
content.

@daniel-noland daniel-noland force-pushed the pr/daniel-noland/ci-security branch 4 times, most recently from 22c1a70 to f94f266 Compare July 1, 2026 23:26
daniel-noland and others added 10 commits July 1, 2026 18:47
I updated Cargo.lock to keep the other diffs as clean as possible.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
Pin every third-party `uses:` reference (marketplace actions and
composite actions) to a specific commit SHA, with the resolved tag
kept as a trailing comment for readability. Managed going forward
via `pinact run` (config in .pinact.yaml).

The one exception is the cross-repo reusable workflow
`githedgehog/fabricator/.github/workflows/run-vlab.yaml`: we control
that workflow and pinning it is not desired.  It floats intentionally
and should pose no meaningful security issue.

.pinact.yaml also sets a 10-day `min_age` so `pinact run` never adopts
an action release less than 10 days old.

Also adds `pinact` to the nix devshell so it can be run locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
Trim GITHUB_TOKEN permissions to what each job actually consumes,
traced through the composite actions and justfile recipes:

- bump.yml / version-bump.yml: the blanket contents/id-token/
  pull-requests grants had no consumer -- the actual git push and PR
  creation go through a separately-minted, already-scoped GitHub App
  token, not GITHUB_TOKEN. Reduced to `contents: read` (needed for
  checkout on this private repo).
- dev.yml: same story for the shared `check-perms` block (check,
  sanitize, test_each, concurrency, miri, wasm, cross) -- none of
  those jobs build or push containers, so checks/pull-requests/
  packages/id-token were dead weight. `build` and `publish` keep
  `packages: write` since they push images via `just push-container`.
  `check_changes` keeps `pull-requests: read` for dorny/paths-filter's
  API-based file-list lookup on PR events.

Also scope the three `create-github-app-token` steps (bump.yml,
dev.yml, version-bump.yml) to `permission-contents`/
`permission-pull-requests` instead of inheriting the full GitHub App
installation's permissions, and set `persist-credentials: false` on
checkout steps that never push with the default token (bump.yml,
dev.yml, fossa.yml, lint-validate-dependabot.yml), plus add zizmor to
the nix devshell used to audit this.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
- Name the previously-anonymous cargo-upgrades, version, publish,
  commitlint, and validate jobs (zizmor anonymous-definition).
- Add a concurrency group to mergeability.yml and
  lint-validate-dependabot.yml (zizmor concurrency-limits); the
  former falls back to github.run_id for merge_group events so an
  in-progress merge-queue check is never cancelled.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
Give each linter its own just recipe (clippy, opengrep, pinact,
zizmor) instead of burying cargo clippy alone in `lint`, then compose
them in the justfile.  This gives local parity with the individual CI
lint jobs and a single place to tune each tool's flags.

dev.yml's `check` job now calls the `clippy` recipe directly (it
already ran individual recipes like fmt/test/doctest rather than the
aggregate `lint`; this keeps that step's naming honest).
lint-opengrep.yml now delegates to `just opengrep` instead of
duplicating the scan invocation inline.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
Fold actionlint, cargo-fmt's sibling checks, license-headers, opengrep,
pinact, and zizmor into one non-matrixed `lint` job in dev.yml instead
of six independent lint-*.yml workflows, each of which paid for its
own nix-shell/cachix pull. One job now means one pull per PR instead
of six.

check-dependencies moves here too, off of the check job's debug/release
matrix and out of build's inline step list. `build` (and therefore
`publish`, which pushes to our container registry) now depends on the
whole `lint` job via `needs:`, so a check-dependencies failure still
blocks a container push.

Adds .github/zizmor.yml carrying an unpinned-uses `ref-pin` policy for
the fabricator run-vlab reusable workflow, so zizmor accepts its
`@master` ref pin (which pinact can't SHA-pin; see the pinning commit).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
Add a commitlint check to the same job, gated by a config
(.commitlintrc.yaml) that mirrors the type list and header-length
intent of the existing lint-commitlint.yml action, no trailing
period, roughly 72-char headers. commitlint-rs has no single
"whole header length" rule, only a per-field description-max-length.
That bound is looser than the old check in principle.

commitlint-rs's `--from`/`--to` flags are unusable in any
non-interactive shell, CI included: its arg-handling checks stdin
before checking --from/--to, and stdin is never a TTY there, so it
silently lints empty/stray stdin content instead of the requested
commit range. Worked around by feeding each commit's message to
commitlint individually over stdin instead, which is the one
invocation mode that actually works.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
Steps in a job run sequentially and stop at the first failure, so as
written, a fmt failure would hide whatever clippy/opengrep/zizmor/
pinact/actionlint/license-headers would have said -- a step backwards
from the six independent jobs this replaced, which all ran in parallel
and reported together.

Mark each check `continue-on-error` and add a final step that checks
every step's outcome and fails the job if any of them didn't succeed.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
Extract the dependency-bump logic that lived inline in bump.yml into
just recipes so it can be run and tested locally:

- `bump-cargo-deps` runs `cargo update` plus per-package
  `cargo upgrade`, committing each bump separately, and (in CI) emits
  the PR-body summary via GITHUB_OUTPUT. It uses mktemp scratch files
  and guards the GITHUB_* writes so it is safe to run outside Actions.
- `bump-actions` runs `pinact run --update` to refresh pinned action
  SHAs; available for manual/local use.

bump.yml now calls `just bump-cargo-deps` and drives check-dependencies
through the shared `just` composite action instead of duplicating the
recipe bodies inline. It also switches the app-token input from the
deprecated `app-id` to `client-id` and adds the `ci:+vlab` label to
generated PRs.

Also bumps the dependabot cooldown from 7 to 10 days to match the
pinact `min_age`, so automated dependency PRs wait the same window
before adopting a fresh release.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
The cross compile job isn't run that frequently, but when failures
happen it is very annoying to debug because the max-parallel setting
of 1 makes failures take a long time. Increasing to 2 is very helpful
here and doesn't tax CI too much.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Signed-off-by: Daniel Noland <[email protected]>
@daniel-noland daniel-noland force-pushed the pr/daniel-noland/ci-security branch from f94f266 to 9fd2c20 Compare July 2, 2026 00:47

@qmonnet qmonnet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good, thank you.

My two main questions:

  • Can you double-check (and ideally comment on) the change from app-id to client-id in bump.yml? I note this makes it inconsistent with dev.yml and version-bump.yml, by the way.

  • It seems to me that we want to call just bump-actions as part of bump.yml to avoid Dependabot opening too many PRs for GitHub Actions updates?

Comment thread justfile
declare -r BASE

# Run "cargo update"
echo "::notice::Running cargo update"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Note: we could use a print_notice() wrapper to print ::notice:: in GitHub Actions and format differently outside of it, but it's absolutely fine to keep that for a follow-up or even to keep it like this, I don't expect us to run this locally very often anyway.

Comment thread justfile
Comment on lines +531 to +532
echo "| name | old | req | compatible | latest |";
echo "|------|-----|-----|------------|--------|";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: The columns size won't be automatically adjusted, so I'd pick a larger width for the "name" column; then I think with awk you have printf available and that you can pad the fields to keep something nicely aligned.

Doesn't matter much, though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In fact, why not reuse the same logic as we had previously?

          # Create Pull Request description
          echo "### :rocket: Upgrades available";
          if [[ "${nb_upgrades}" -ge 1 ]]; then
              {
                  echo ""
                  echo "\`\`\`"
                  cat "${upgrade_output}"
                  echo "\`\`\`"
              } > "${upgrade_log}"
          fi

Comment on lines -38 to +39
app-id: "${{ secrets.DP_APP_ID }}"
client-id: "${{ secrets.DP_APP_ID }}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just double-checking, is this intentional?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yup. app-id is deprecated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

OK thanks, would you mind fixing the other workflows in this case, please?

Comment thread justfile
Comment on lines +463 to +466
[script]
bump-actions:
{{ _just_debuggable_ }}
pinact run --update

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good, but shouldn't we call this from the bump.yml workflow to update GitHub Actions on a periodical basis, before the cooldown for Dependabot ends and it starts opening its own PRs? I don't see bump-actions called in CI at the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:+cross/full ci:+vlab Enable VLAB tests ci Continuous Integration clean-up Code base clean-up, no functional change dependencies Pull requests that update a dependency file

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants