Skip to content

ci: harden GitHub Actions with permissions, SHA pins, and cache restrictions - #154

Merged
avifenesh merged 8 commits into
mainfrom
feature/harden-gh-actions-91
Feb 4, 2026
Merged

ci: harden GitHub Actions with permissions, SHA pins, and cache restrictions#154
avifenesh merged 8 commits into
mainfrom
feature/harden-gh-actions-91

Conversation

@avifenesh

Copy link
Copy Markdown
Collaborator

Summary

  • Hardened all 7 GitHub Actions workflows with security best practices
  • Added explicit permissions blocks following principle of least privilege
  • SHA-pinned all third-party actions to prevent supply chain attacks
  • Restricted cache saves to main branch only to prevent cache poisoning

Changes

Permissions Hardening

  • Added permissions: contents: read to ci.yml, changelog.yml, test-action.yml
  • Added permissions: {} to claude.yml, claude-code-review.yml (jobs have specific permissions)
  • release.yml and security.yml already had correct permissions

SHA Pinning (10 unique actions)

Action SHA
actions/checkout@v4 34e114876b0b11c390a56381ad16ebd13914f8d5
actions/upload-artifact@v4 ea165f8d65b6e75b540449e92b4886f43607fa02
actions/download-artifact@v4 d3f86a106a0bac45b974a628896c90dbdf5c8093
dtolnay/rust-toolchain@stable 4be9e76fd7c4901c61fb841f559994984270fce7
Swatinem/rust-cache@v2 779680da715d629ac1d338a641029a2f4372abb5
taiki-e/install-action@v2 650c5ca14212efbbf3e580844b04bdccf68dac31
taiki-e/install-action@nextest cd05dcd6eb73067dda063b97a15b7060049dacd9
github/codeql-action@v3 2588666de8825e1e9dc4e2329a4c985457d55b32
softprops/action-gh-release@v2 a06a81a03ee405af7f2048a818ed3f03bbf83c7b
anthropics/claude-code-action@v1 6867bb3ab0b2c0a10629b6823e457347e74ad6d2

Cache Hardening

  • Added save-if: ${{ github.ref == 'refs/heads/main' }} to all rust-cache usages
  • Prevents cache poisoning from pull request branches

Documentation

  • Added .github/workflows/README.md documenting the SHA pinning strategy
  • Updated CHANGELOG.md with security section entry

Closes #91

Test plan

  • All 744 tests pass
  • Release build succeeds
  • YAML syntax validated for all workflow files
  • CI workflows execute successfully after merge

- Add workflow-level permissions: contents: read
- Pin all actions to SHA commits with version comments
- Add save-if restrictions to rust-cache (only save on main branch)
…ictions

release.yml:
- Pin all actions to SHA commits with version comments
- Add save-if restriction to rust-cache (only save on tag pushes)

security.yml:
- Pin all actions to SHA commits with version comments
- Add save-if restriction to rust-cache (only save on main branch)
test-action.yml:
- Add workflow-level permissions: contents: read
- Pin all actions to SHA commits with version comments
- Add save-if restrictions to both rust-cache usages

changelog.yml:
- Add workflow-level permissions: contents: read
- Pin checkout action to SHA commit

claude.yml:
- Add workflow-level permissions: {} (jobs specify their own)
- Pin checkout and claude-code-action to SHA commits

claude-code-review.yml:
- Add workflow-level permissions: {} (job specifies its own)
- Pin checkout and claude-code-action to SHA commits
- Document security hardening approach (permissions, SHA pins, cache restrictions)
- Provide SHA pin reference table for all actions used
- Include instructions for updating action versions
- Add workflow overview table
Copilot AI review requested due to automatic review settings February 4, 2026 10:10
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @avifenesh, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the security posture of the project's continuous integration pipelines. By applying a set of best practices, it aims to reduce potential vulnerabilities related to workflow permissions, the integrity of third-party actions, and cache security, thereby making the CI/CD process more robust and trustworthy.

Highlights

  • GitHub Actions Security Hardening: Implemented security best practices across all 7 GitHub Actions workflows to enhance overall pipeline security.
  • Principle of Least Privilege: Explicit permissions blocks were added to all workflows, ensuring that actions only have the minimum necessary access required for their operations.
  • Supply Chain Security: All third-party GitHub Actions are now SHA-pinned to specific commit hashes, mitigating risks associated with supply chain attacks and ensuring consistent action versions.
  • Cache Poisoning Prevention: GitHub Actions cache saves are restricted to the main branch only, preventing potential cache poisoning from pull request branches.
  • Documentation and Changelog: A new README.md was added to document the SHA pinning strategy, and the CHANGELOG.md was updated to reflect these security enhancements.
Changelog
  • CHANGELOG.md
    • Hardened GitHub Actions workflows with security best practices.
    • Added explicit permissions blocks to all workflows (principle of least privilege).
    • SHA-pinned all third-party actions to prevent supply chain attacks.
    • Restricted cache saves to main branch only (prevents cache poisoning from PRs).
    • Documented SHA pin reference in .github/workflows/README.md for maintainability.
Ignored Files
  • Ignored by pattern: .github/workflows/** (8)
    • .github/workflows/README.md
    • .github/workflows/changelog.yml
    • .github/workflows/ci.yml
    • .github/workflows/claude-code-review.yml
    • .github/workflows/claude.yml
    • .github/workflows/release.yml
    • .github/workflows/security.yml
    • .github/workflows/test-action.yml
Activity
  • No specific activity (comments, reviews, progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 71d9739a79

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@@ -170,12 +175,14 @@ jobs:
security-events: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include contents read when overriding job permissions

The workflow now sets permissions: contents: read at the top level, but this job overrides it with a job-level permissions block that only includes security-events: write. Job-level permissions replace workflow defaults, so this job no longer has contents: read, which actions/checkout relies on. That means the Test SARIF Upload job will fail at checkout when the hardened permissions change takes effect. Add contents: read to this job’s permissions to keep checkout working while still limiting access.

Useful? React with 👍 / 👎.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces significant security hardening for the GitHub Actions workflows, and the changes are well-documented in the changelog. The new entry is clear and correctly placed under the ### Security section. I've added one comment regarding the changelog structure to improve its overall consistency and readability.

Comment thread CHANGELOG.md
- Restricted cache saves to main branch only (prevents cache poisoning from PRs)
- Documented SHA pin reference in .github/workflows/README.md for maintainability

### Added

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.

medium

This changelog appears to have multiple ### Added sections under ## [Unreleased]. According to the 'Keep a Changelog' format, there should only be one of each heading type per release. To improve clarity and consistency, consider consolidating all new features under the first ### Added section (at line 10).

Job-level permissions override workflow defaults, so the checkout
action needs explicit contents:read permission in addition to
security-events:write.

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 pull request implements comprehensive security hardening for all GitHub Actions workflows in the repository, addressing issue #91. The changes follow security best practices to reduce supply chain attack risks and prevent cache poisoning attacks.

Changes:

  • Added explicit permissions blocks to all 7 workflows following the principle of least privilege
  • SHA-pinned 10 unique third-party actions to specific commit hashes to prevent supply chain attacks
  • Restricted cache saves to protected branches (main) and tag pushes to prevent cache poisoning from pull requests
  • Added comprehensive documentation in .github/workflows/README.md to guide future maintenance

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
.github/workflows/ci.yml Added permissions block and SHA-pinned all actions; restricted cache saves to main branch
.github/workflows/changelog.yml Added permissions block and SHA-pinned checkout action
.github/workflows/test-action.yml Added permissions block, SHA-pinned actions, and restricted cache saves to main branch
.github/workflows/security.yml SHA-pinned all actions and restricted cache saves to main branch
.github/workflows/release.yml SHA-pinned all actions and restricted cache saves to tag pushes
.github/workflows/claude.yml Added empty permissions block at workflow level and SHA-pinned actions
.github/workflows/claude-code-review.yml Added empty permissions block at workflow level and SHA-pinned actions
.github/workflows/README.md Added comprehensive documentation of security practices, SHA pin reference table, and update procedures
CHANGELOG.md Added Security section entry documenting the workflow hardening changes

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
save-if: ${{ github.ref == 'refs/heads/main' }}

Copilot AI Feb 4, 2026

Copy link

Choose a reason for hiding this comment

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

The cache save restriction in test-action.yml only allows caching on the main branch, but this workflow is configured to run on feature/* and fix/* branches (see lines 5-9). This means builds on feature/* and fix/* branches will never be able to save caches, potentially slowing down development on these branches.

Consider whether these branches should also be allowed to save caches, or if the trigger pattern should be restricted. The current configuration prevents cache poisoning but may impact developer experience on feature branches.

Suggested change
save-if: ${{ github.ref == 'refs/heads/main' }}
save-if: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/feature/') || startsWith(github.ref, 'refs/heads/fix/') }}

Copilot uses AI. Check for mistakes.
Comment thread CHANGELOG.md
- Restricted cache saves to main branch only (prevents cache poisoning from PRs)
- Documented SHA pin reference in .github/workflows/README.md for maintainability

### Added

Copilot AI Feb 4, 2026

Copy link

Choose a reason for hiding this comment

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

The CHANGELOG now has duplicate "### Added" sections (one at line 10 and one at line 63). According to Keep a Changelog format, each section type should appear only once per release. The two "### Added" sections should be merged into a single section.

Copilot uses AI. Check for mistakes.
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
with:
key: release-${{ matrix.target }}
save-if: ${{ startsWith(github.ref, 'refs/tags/') }}

Copilot AI Feb 4, 2026

Copy link

Choose a reason for hiding this comment

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

The release.yml workflow uses a different cache save condition than described in the PR description. The description states "Restricted cache saves to main branch only" but release.yml correctly uses startsWith(github.ref, 'refs/tags/') instead since it runs on tag pushes, not on main branch pushes. While the implementation is correct, the PR description could be more precise about this distinction.

Copilot uses AI. Check for mistakes.
- Merged duplicate ### Added sections into one
- Removed duplicate ### Fixed section (content already present)
- Now follows Keep a Changelog format with one heading per type
Copilot AI review requested due to automatic review settings February 4, 2026 10:36
@avifenesh
avifenesh merged commit 0602856 into main Feb 4, 2026
19 of 20 checks passed

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 9 out of 9 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread CHANGELOG.md
Comment on lines 10 to 63
@@ -55,8 +47,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New `file_utils` module with `safe_read_file()` using `symlink_metadata()`
- Applied to validation, imports, fixes, and config loading
- Cross-platform tests for Unix and Windows symlink handling
- Hardened GitHub Actions workflows with security best practices:
- Added explicit permissions blocks to all workflows (principle of least privilege)
- SHA-pinned all third-party actions to prevent supply chain attacks
- Restricted cache saves to main branch only (prevents cache poisoning from PRs)
- Documented SHA pin reference in .github/workflows/README.md for maintainability

### Added
- MCP-008 rule for protocol version validation with configurable `mcp_protocol_version` option
- 5 new parse error rules with normalized IDs (AS-016, CC-HK-012, CC-AG-007, CC-PL-006, MCP-007)
- Auto-fix support for CC-MEM-005 and CC-MEM-007 memory rules
- CC-MEM-005: Delete lines containing generic instructions
- CC-MEM-007: Replace weak constraint language with stronger alternatives
- CRLF line ending support for correct byte offsets on Windows
- Auto-fix implementations for five additional rules:

Copilot AI Feb 4, 2026

Copy link

Choose a reason for hiding this comment

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

The CHANGELOG structure has been reorganized in a way that moves existing entries around. Specifically, the "Added" section entries for MCP-008, parse error rules, and auto-fix support (originally at lines 10-19) have been moved to after the new Security entry (lines 56-62). Additionally, the "Fixed" section entries for exclude glob patterns and PE-001 rules (originally at lines 227-234) appear to have been removed entirely.

This reorganization may cause confusion as it modifies existing changelog entries from their original position. Keep a Changelog best practices suggest that entries should be added to their respective sections without reorganizing existing content. If these entries were meant to stay in the Unreleased section, they should remain in their original order with new entries added above them or in a consistent pattern.

Copilot uses AI. Check for mistakes.
@avifenesh
avifenesh deleted the feature/harden-gh-actions-91 branch February 5, 2026 12:48
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.

Harden GitHub Actions permissions, pins, and caches

2 participants