fix: pin GitHub Actions to immutable SHA hashes to prevent supply chain attacks (#1088)

* chore: publish from staged

* fix: pin GitHub Actions to immutable SHA hashes to prevent supply chain attacks

Co-authored-by: simonkurtz-MSFT <84809797+simonkurtz-MSFT@users.noreply.github.com>

* chore: publish from staged

* Clean plugins

* Clean plugins

* Clean plugins

* Fix gem-team plugin

* Reset README.plugins.md

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
Simon Kurtz
2026-03-22 18:37:40 -05:00
committed by GitHub
parent 10e717202f
commit 919fdb3f8e
13 changed files with 52 additions and 50 deletions

View File

@@ -13,7 +13,7 @@ jobs:
check-line-endings: check-line-endings:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: Check for CRLF line endings in markdown files - name: Check for CRLF line endings in markdown files
run: | run: |

View File

@@ -15,10 +15,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Check for materialized files in plugin directories - name: Check for materialized files in plugin directories
uses: actions/github-script@v7 uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
with: with:
script: | script: |
const { execSync } = require('child_process'); const { execSync } = require('child_process');

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Reject PR targeting main - name: Reject PR targeting main
uses: actions/github-script@v7 uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
with: with:
script: | script: |
const body = [ const body = [

View File

@@ -13,10 +13,10 @@ jobs:
codespell: codespell:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Check spelling with codespell - name: Check spelling with codespell
uses: codespell-project/actions-codespell@v2 uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2.1
with: with:
check_filenames: true check_filenames: true
check_hidden: false check_hidden: false

View File

@@ -14,7 +14,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -25,7 +25,7 @@ jobs:
echo "version=${NODE_VERSION}" >> "$GITHUB_OUTPUT" echo "version=${NODE_VERSION}" >> "$GITHUB_OUTPUT"
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version: ${{ steps.node-version.outputs.version }} node-version: ${{ steps.node-version.outputs.version }}
@@ -71,7 +71,7 @@ jobs:
- name: Create Pull Request - name: Create Pull Request
if: steps.verify-changed-files.outputs.changed == 'true' if: steps.verify-changed-files.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v7 uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "docs: update contributors" commit-message: "docs: update contributors"

View File

@@ -19,7 +19,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install gh-aw extension - name: Install gh-aw extension
uses: github/gh-aw/actions/setup-cli@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2 uses: github/gh-aw/actions/setup-cli@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2
with: with:

View File

@@ -25,12 +25,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with: with:
fetch-depth: 0 # Full history needed for git-based last updated dates fetch-depth: 0 # Full history needed for git-based last updated dates
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: "20" node-version: "20"
cache: "npm" cache: "npm"
@@ -50,10 +50,10 @@ jobs:
working-directory: ./website working-directory: ./website
- name: Setup Pages - name: Setup Pages
uses: actions/configure-pages@v5 uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@v3 uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
with: with:
path: "./website/dist" path: "./website/dist"
@@ -67,4 +67,4 @@ jobs:
steps: steps:
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@v4 uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout staged branch - name: Checkout staged branch
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with: with:
ref: staged ref: staged
fetch-depth: 0 fetch-depth: 0
@@ -29,7 +29,7 @@ jobs:
echo "version=${NODE_VERSION}" >> "$GITHUB_OUTPUT" echo "version=${NODE_VERSION}" >> "$GITHUB_OUTPUT"
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: ${{ steps.node-version.outputs.version }} node-version: ${{ steps.node-version.outputs.version }}

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -49,7 +49,7 @@ jobs:
- name: Comment on PR - name: Comment on PR
if: failure() if: failure()
uses: marocchino/sticky-pull-request-comment@v2 uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4
with: with:
header: workflow-forbidden-files header: workflow-forbidden-files
message: | message: |
@@ -74,10 +74,10 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Install gh-aw CLI - name: Install gh-aw CLI
uses: github/gh-aw/actions/setup-cli@main uses: github/gh-aw/actions/setup-cli@f7437f4f94c2bc86e7e6eca0f374e303e98bd66c # v0.61.1
- name: Compile workflow files - name: Compile workflow files
id: compile id: compile
@@ -111,7 +111,7 @@ jobs:
- name: Comment on PR if compilation failed - name: Comment on PR if compilation failed
if: failure() if: failure()
uses: marocchino/sticky-pull-request-comment@v2 uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4
with: with:
header: workflow-validation header: workflow-validation
message: | message: |

View File

@@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with: with:
node-version: "20" node-version: "20"
@@ -66,7 +66,7 @@ jobs:
- name: Comment on PR if files need updating - name: Comment on PR if files need updating
if: steps.check-diff.outputs.status == 'failure' && github.event.pull_request.head.repo.permissions.push == true if: steps.check-diff.outputs.status == 'failure' && github.event.pull_request.head.repo.permissions.push == true
uses: marocchino/sticky-pull-request-comment@v2 uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4
with: with:
header: readme-validation header: readme-validation
message: | message: |

View File

@@ -41,10 +41,12 @@ Before creating or modifying workflows:
- Grant minimal necessary permissions - Grant minimal necessary permissions
**Action Pinning**: **Action Pinning**:
- Pin to specific versions for stability - Always pin actions to a full-length commit SHA for maximum security and immutability (e.g., `actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1`)
- Use major version tags (`@v4`) for balance of security and maintenance - **Never use mutable references** such as `@main`, `@latest`, or major version tags (e.g., `@v4`) — tags can be silently moved by a repository owner or attacker to point to a malicious commit, enabling supply chain attacks that execute arbitrary code in your CI/CD pipeline
- Consider full commit SHA for maximum security (requires more maintenance) - A commit SHA is immutable: once set, it cannot be changed or redirected, providing a cryptographic guarantee about exactly what code will run
- Never use `@main` or `@latest` - Add a version comment (e.g., `# v4.3.1`) next to the SHA so humans can quickly understand what version is pinned
- This applies to **all** actions, including first-party (`actions/`) and especially third-party actions where you have no control over tag mutations
- Use `dependabot` or Renovate to automate SHA updates when new action versions are released
**Secrets**: **Secrets**:
- Access via environment variables only - Access via environment variables only
@@ -89,7 +91,7 @@ Eliminate long-lived credentials:
## Workflow Security Checklist ## Workflow Security Checklist
- [ ] Actions pinned to specific versions - [ ] Actions pinned to full commit SHAs with version comments (e.g., `uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1`)
- [ ] Permissions: least privilege (default `contents: read`) - [ ] Permissions: least privilege (default `contents: read`)
- [ ] Secrets via environment variables only - [ ] Secrets via environment variables only
- [ ] OIDC for cloud authentication - [ ] OIDC for cloud authentication
@@ -107,7 +109,7 @@ Eliminate long-lived credentials:
## Best Practices Summary ## Best Practices Summary
1. Pin actions to specific versions 1. Pin actions to full commit SHAs with version comments (e.g., `@<sha> # vX.Y.Z`) — never use mutable tags or branches
2. Use least privilege permissions 2. Use least privilege permissions
3. Never log secrets 3. Never log secrets
4. Prefer OIDC for cloud access 4. Prefer OIDC for cloud access

View File

@@ -59,7 +59,7 @@ Build reliable CI/CD pipelines, debug deployment failures quickly, and ensure ev
18.16.0 18.16.0
# CI config (.github/workflows/deploy.yml) # CI config (.github/workflows/deploy.yml)
- uses: actions/setup-node@v3 - uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
``` ```
@@ -112,7 +112,7 @@ main:
run: npm audit --audit-level=high run: npm audit --audit-level=high
- name: Secret scanning - name: Secret scanning
uses: trufflesecurity/trufflehog@main uses: trufflesecurity/trufflehog@6c05c4a00b91aa542267d8e32a8254774799d68d # v3.93.8
``` ```
## Step 4: Debugging Methodology ## Step 4: Debugging Methodology
@@ -209,7 +209,7 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- run: npm ci - run: npm ci
- run: npm test - run: npm test

View File

@@ -47,9 +47,9 @@ jobs:
artifact_path: ${{ steps.package_app.outputs.path }} artifact_path: ${{ steps.package_app.outputs.path }}
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v3 uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1
with: with:
node-version: 18 node-version: 18
- name: Install dependencies and build - name: Install dependencies and build
@@ -62,7 +62,7 @@ jobs:
zip -r dist.zip dist zip -r dist.zip dist
echo "path=dist.zip" >> "$GITHUB_OUTPUT" echo "path=dist.zip" >> "$GITHUB_OUTPUT"
- name: Upload build artifact - name: Upload build artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with: with:
name: my-app-build name: my-app-build
path: dist.zip path: dist.zip
@@ -74,7 +74,7 @@ jobs:
environment: staging environment: staging
steps: steps:
- name: Download build artifact - name: Download build artifact
uses: actions/download-artifact@v3 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with: with:
name: my-app-build name: my-app-build
- name: Deploy to Staging - name: Deploy to Staging
@@ -87,17 +87,17 @@ jobs:
### **3. Steps and Actions** ### **3. Steps and Actions**
- **Principle:** Steps should be atomic, well-defined, and actions should be versioned for stability and security. - **Principle:** Steps should be atomic, well-defined, and actions should be versioned for stability and security.
- **Deeper Dive:** - **Deeper Dive:**
- **`uses`:** Referencing marketplace actions (e.g., `actions/checkout@v4`, `actions/setup-node@v3`) or custom actions. Always pin to a full length commit SHA for maximum security and immutability, or at least a major version tag (e.g., `@v4`). Avoid pinning to `main` or `latest`. - **`uses`:** Referencing marketplace actions (e.g., `actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2`) or custom actions. Always pin to a full-length commit SHA for maximum security and immutability. Tags and branches are mutable references — a malicious actor who gains write access to an action's repository can silently move a tag (e.g., `@v4`) to a compromised commit, executing arbitrary code in your workflow (a supply chain attack). A commit SHA is immutable and cannot be redirected. Add the version as a comment (e.g., `# v4.3.1`) for human readability. Avoid mutable references like `@main`, `@latest`, or major version tags (e.g., `@v4`).
- **`name`:** Essential for clear logging and debugging. Make step names descriptive. - **`name`:** Essential for clear logging and debugging. Make step names descriptive.
- **`run`:** For executing shell commands. Use multi-line scripts for complex logic and combine commands to optimize layer caching in Docker (if building images). - **`run`:** For executing shell commands. Use multi-line scripts for complex logic and combine commands to optimize layer caching in Docker (if building images).
- **`env`:** Define environment variables at the step or job level. Do not hardcode sensitive data here. - **`env`:** Define environment variables at the step or job level. Do not hardcode sensitive data here.
- **`with`:** Provide inputs to actions. Ensure all required inputs are present. - **`with`:** Provide inputs to actions. Ensure all required inputs are present.
- **Guidance for Copilot:** - **Guidance for Copilot:**
- Use `uses` to reference marketplace or custom actions, always specifying a secure version (tag or SHA). - Use `uses` to reference marketplace or custom actions, always pinning to an immutable commit SHA with a human-readable version comment (e.g., `uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2`). This is especially critical for third-party actions where you have no control over whether a tag gets moved.
- Use `name` for each step for readability in logs and easier debugging. - Use `name` for each step for readability in logs and easier debugging.
- Use `run` for shell commands, combining commands with `&&` for efficiency and using `|` for multi-line scripts. - Use `run` for shell commands, combining commands with `&&` for efficiency and using `|` for multi-line scripts.
- Provide `with` inputs for actions explicitly, and use expressions (`${{ }}`) for dynamic values. - Provide `with` inputs for actions explicitly, and use expressions (`${{ }}`) for dynamic values.
- **Security Note:** Audit marketplace actions before use. Prefer actions from trusted sources (e.g., `actions/` organization) and review their source code if possible. Use `dependabot` for action version updates. - **Security Note:** Audit marketplace actions before use. Prefer actions from trusted sources (e.g., `actions/` organization) and review their source code if possible. Use `dependabot` for action version updates. **Never use mutable tag or branch references** (`@v4`, `@main`, `@latest`) — these are vulnerable to supply chain attacks where a compromised tag can execute malicious code in your CI/CD pipeline.
## Security Best Practices in GitHub Actions ## Security Best Practices in GitHub Actions
@@ -136,7 +136,7 @@ jobs:
- **Federated Identity:** This is a key pattern for modern, secure cloud deployments. - **Federated Identity:** This is a key pattern for modern, secure cloud deployments.
- **Guidance for Copilot:** - **Guidance for Copilot:**
- Strongly recommend OIDC for authenticating with AWS, Azure, GCP, and other cloud providers instead of storing long-lived access keys as secrets. - Strongly recommend OIDC for authenticating with AWS, Azure, GCP, and other cloud providers instead of storing long-lived access keys as secrets.
- Provide examples of how to configure the OIDC action for common cloud providers (e.g., `aws-actions/configure-aws-credentials@v4`). - Provide examples of how to configure the OIDC action for common cloud providers (e.g., `aws-actions/configure-aws-credentials@<SHA> # v4.x.x`). Always pin to a full commit SHA.
- Explain the concept of trust policies and how they relate to OIDC setup. - Explain the concept of trust policies and how they relate to OIDC setup.
- **Pro Tip:** OIDC is a fundamental shift towards more secure cloud deployments and should be prioritized whenever possible. - **Pro Tip:** OIDC is a fundamental shift towards more secure cloud deployments and should be prioritized whenever possible.
@@ -162,7 +162,7 @@ jobs:
permissions: permissions:
contents: read # This job only needs to read code, override workflow default contents: read # This job only needs to read code, override workflow default
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- run: npm run lint - run: npm run lint
``` ```
@@ -219,13 +219,13 @@ jobs:
- **Restore Keys:** Use `restore-keys` for fallbacks to older, compatible caches. - **Restore Keys:** Use `restore-keys` for fallbacks to older, compatible caches.
- **Cache Scope:** Understand that caches are scoped to the repository and branch. - **Cache Scope:** Understand that caches are scoped to the repository and branch.
- **Guidance for Copilot:** - **Guidance for Copilot:**
- Use `actions/cache@v3` for caching common package manager dependencies (Node.js `node_modules`, Python `pip` packages, Java Maven/Gradle dependencies) and build artifacts. - Use `actions/cache` (pinned to a full commit SHA) for caching common package manager dependencies (Node.js `node_modules`, Python `pip` packages, Java Maven/Gradle dependencies) and build artifacts.
- Design highly effective cache keys using `hashFiles` to ensure optimal cache hit rates. - Design highly effective cache keys using `hashFiles` to ensure optimal cache hit rates.
- Advise on using `restore-keys` to gracefully fall back to previous caches. - Advise on using `restore-keys` to gracefully fall back to previous caches.
- **Example (Advanced Caching for Monorepo):** - **Example (Advanced Caching for Monorepo):**
```yaml ```yaml
- name: Cache Node.js modules - name: Cache Node.js modules
uses: actions/cache@v3 uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with: with:
path: | path: |
~/.npm ~/.npm
@@ -259,8 +259,8 @@ jobs:
node-version: [16.x, 18.x, 20.x] node-version: [16.x, 18.x, 20.x]
browser: [chromium, firefox] browser: [chromium, firefox]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/setup-node@v3 - uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1
with: with:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: Install Playwright browsers - name: Install Playwright browsers
@@ -289,7 +289,7 @@ jobs:
- **`lfs`:** Manage Git LFS (Large File Storage) files efficiently. If not needed, set `lfs: false`. - **`lfs`:** Manage Git LFS (Large File Storage) files efficiently. If not needed, set `lfs: false`.
- **Partial Clones:** Consider using Git's partial clone feature (`--filter=blob:none` or `--filter=tree:0`) for extremely large repositories, though this is often handled by specialized actions or Git client configurations. - **Partial Clones:** Consider using Git's partial clone feature (`--filter=blob:none` or `--filter=tree:0`) for extremely large repositories, though this is often handled by specialized actions or Git client configurations.
- **Guidance for Copilot:** - **Guidance for Copilot:**
- Use `actions/checkout@v4` with `fetch-depth: 1` as the default for most build and test jobs to significantly save time and bandwidth. - Use `actions/checkout` (pinned to a full commit SHA, e.g., `actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1`) with `fetch-depth: 1` as the default for most build and test jobs to significantly save time and bandwidth.
- Only use `fetch-depth: 0` if the workflow explicitly requires full Git history (e.g., for release tagging, deep commit analysis, or `git blame` operations). - Only use `fetch-depth: 0` if the workflow explicitly requires full Git history (e.g., for release tagging, deep commit analysis, or `git blame` operations).
- Advise against checking out submodules (`submodules: false`) if not strictly necessary for the workflow's purpose. - Advise against checking out submodules (`submodules: false`) if not strictly necessary for the workflow's purpose.
- Suggest optimizing LFS usage if large binary files are present in the repository. - Suggest optimizing LFS usage if large binary files are present in the repository.
@@ -303,7 +303,7 @@ jobs:
- **Use Cases:** Build outputs (executables, compiled code, Docker images), test reports (JUnit XML, HTML reports), code coverage reports, security scan results, generated documentation, static website builds. - **Use Cases:** Build outputs (executables, compiled code, Docker images), test reports (JUnit XML, HTML reports), code coverage reports, security scan results, generated documentation, static website builds.
- **Limitations:** Artifacts are immutable once uploaded. Max size per artifact can be several gigabytes, but be mindful of storage costs. - **Limitations:** Artifacts are immutable once uploaded. Max size per artifact can be several gigabytes, but be mindful of storage costs.
- **Guidance for Copilot:** - **Guidance for Copilot:**
- Use `actions/upload-artifact@v3` and `actions/download-artifact@v3` to reliably pass large files between jobs within the same workflow or across different workflows, promoting modularity and efficiency. - Use `actions/upload-artifact` and `actions/download-artifact` (both pinned to full commit SHAs) to reliably pass large files between jobs within the same workflow or across different workflows, promoting modularity and efficiency.
- Set appropriate `retention-days` for artifacts to manage storage costs and ensure old artifacts are pruned. - Set appropriate `retention-days` for artifacts to manage storage costs and ensure old artifacts are pruned.
- Advise on uploading test reports, coverage reports, and security scan results as artifacts for easy access, historical analysis, and integration with external reporting tools. - Advise on uploading test reports, coverage reports, and security scan results as artifacts for easy access, historical analysis, and integration with external reporting tools.
- Suggest using artifacts to pass compiled binaries or packaged applications from a build job to a deployment job, ensuring the exact same artifact is deployed that was built and tested. - Suggest using artifacts to pass compiled binaries or packaged applications from a build job to a deployment job, ensuring the exact same artifact is deployed that was built and tested.
@@ -452,7 +452,7 @@ This checklist provides a granular set of criteria for reviewing GitHub Actions
- Are `needs` dependencies correctly defined between jobs to ensure proper execution order? - Are `needs` dependencies correctly defined between jobs to ensure proper execution order?
- Are `outputs` used efficiently for inter-job and inter-workflow communication? - Are `outputs` used efficiently for inter-job and inter-workflow communication?
- Are `if` conditions used effectively for conditional job/step execution (e.g., environment-specific deployments, branch-specific actions)? - Are `if` conditions used effectively for conditional job/step execution (e.g., environment-specific deployments, branch-specific actions)?
- Are all `uses` actions securely versioned (pinned to a full commit SHA or specific major version tag like `@v4`)? Avoid `main` or `latest` tags. - Are all `uses` actions pinned to a full commit SHA with a human-readable version comment (e.g., `actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1`)? Tags (e.g., `@v4`) and branches (e.g., `@main`) are mutable and can be silently redirected to malicious commits — always use immutable SHA references, especially for third-party actions.
- Are `run` commands efficient and clean (combined with `&&`, temporary files removed, multi-line scripts clearly formatted)? - Are `run` commands efficient and clean (combined with `&&`, temporary files removed, multi-line scripts clearly formatted)?
- Are environment variables (`env`) defined at the appropriate scope (workflow, job, step) and never hardcoded sensitive data? - Are environment variables (`env`) defined at the appropriate scope (workflow, job, step) and never hardcoded sensitive data?
- Is `timeout-minutes` set for long-running jobs to prevent hung workflows? - Is `timeout-minutes` set for long-running jobs to prevent hung workflows?