diff --git a/.github/workflows/check-line-endings.yml b/.github/workflows/check-line-endings.yml index 793aaa803..3e7040c0c 100644 --- a/.github/workflows/check-line-endings.yml +++ b/.github/workflows/check-line-endings.yml @@ -13,7 +13,7 @@ jobs: check-line-endings: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - name: Check for CRLF line endings in markdown files run: | diff --git a/.github/workflows/check-plugin-structure.yml b/.github/workflows/check-plugin-structure.yml index e71b3503d..86bab0be6 100644 --- a/.github/workflows/check-plugin-structure.yml +++ b/.github/workflows/check-plugin-structure.yml @@ -15,10 +15,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Check for materialized files in plugin directories - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | const { execSync } = require('child_process'); diff --git a/.github/workflows/check-pr-target.yml b/.github/workflows/check-pr-target.yml index 38c178e7e..d0e5834cd 100644 --- a/.github/workflows/check-pr-target.yml +++ b/.github/workflows/check-pr-target.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Reject PR targeting main - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | const body = [ diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml index 57a89fa90..5c5dae06e 100644 --- a/.github/workflows/codespell.yml +++ b/.github/workflows/codespell.yml @@ -13,10 +13,10 @@ jobs: codespell: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Check spelling with codespell - uses: codespell-project/actions-codespell@v2 + uses: codespell-project/actions-codespell@406322ec52dd7b488e48c1c4b82e2a8b3a1bf630 # v2.1 with: check_filenames: true check_hidden: false diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index 7588b8b6e..21913a64d 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 @@ -25,7 +25,7 @@ jobs: echo "version=${NODE_VERSION}" >> "$GITHUB_OUTPUT" - name: Setup Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: node-version: ${{ steps.node-version.outputs.version }} @@ -71,7 +71,7 @@ jobs: - name: Create Pull Request 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: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "docs: update contributors" diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml index d5d988a3f..11f7144da 100644 --- a/.github/workflows/copilot-setup-steps.yml +++ b/.github/workflows/copilot-setup-steps.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install gh-aw extension uses: github/gh-aw/actions/setup-cli@32b3a711a9ee97d38e3989c90af0385aff0066a7 # v0.57.2 with: diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml index 35210e7fc..0289addbf 100644 --- a/.github/workflows/deploy-website.yml +++ b/.github/workflows/deploy-website.yml @@ -25,12 +25,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 # Full history needed for git-based last updated dates - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "20" cache: "npm" @@ -50,10 +50,10 @@ jobs: working-directory: ./website - name: Setup Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 with: path: "./website/dist" @@ -67,4 +67,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ec288decb..32a538091 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout staged branch - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: ref: staged fetch-depth: 0 @@ -29,7 +29,7 @@ jobs: echo "version=${NODE_VERSION}" >> "$GITHUB_OUTPUT" - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ steps.node-version.outputs.version }} diff --git a/.github/workflows/validate-agentic-workflows-pr.yml b/.github/workflows/validate-agentic-workflows-pr.yml index 625b8b0dd..5f90db8ab 100644 --- a/.github/workflows/validate-agentic-workflows-pr.yml +++ b/.github/workflows/validate-agentic-workflows-pr.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 @@ -49,7 +49,7 @@ jobs: - name: Comment on PR if: failure() - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4 with: header: workflow-forbidden-files message: | @@ -74,10 +74,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - 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 id: compile @@ -111,7 +111,7 @@ jobs: - name: Comment on PR if compilation failed if: failure() - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2.9.4 with: header: workflow-validation message: | diff --git a/.github/workflows/validate-readme.yml b/.github/workflows/validate-readme.yml index e9ae9dfee..f3f81cb4d 100644 --- a/.github/workflows/validate-readme.yml +++ b/.github/workflows/validate-readme.yml @@ -23,12 +23,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "20" @@ -66,7 +66,7 @@ jobs: - name: Comment on PR if files need updating 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: header: readme-validation message: | diff --git a/agents/github-actions-expert.agent.md b/agents/github-actions-expert.agent.md index 943867476..9ad33d993 100644 --- a/agents/github-actions-expert.agent.md +++ b/agents/github-actions-expert.agent.md @@ -41,10 +41,12 @@ Before creating or modifying workflows: - Grant minimal necessary permissions **Action Pinning**: -- Pin to specific versions for stability -- Use major version tags (`@v4`) for balance of security and maintenance -- Consider full commit SHA for maximum security (requires more maintenance) -- Never use `@main` or `@latest` +- Always pin actions to a full-length commit SHA for maximum security and immutability (e.g., `actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1`) +- **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 +- A commit SHA is immutable: once set, it cannot be changed or redirected, providing a cryptographic guarantee about exactly what code will run +- 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**: - Access via environment variables only @@ -89,7 +91,7 @@ Eliminate long-lived credentials: ## 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`) - [ ] Secrets via environment variables only - [ ] OIDC for cloud authentication @@ -107,7 +109,7 @@ Eliminate long-lived credentials: ## Best Practices Summary -1. Pin actions to specific versions +1. Pin actions to full commit SHAs with version comments (e.g., `@ # vX.Y.Z`) — never use mutable tags or branches 2. Use least privilege permissions 3. Never log secrets 4. Prefer OIDC for cloud access diff --git a/agents/se-gitops-ci-specialist.agent.md b/agents/se-gitops-ci-specialist.agent.md index 338a3c0ca..520618637 100644 --- a/agents/se-gitops-ci-specialist.agent.md +++ b/agents/se-gitops-ci-specialist.agent.md @@ -59,7 +59,7 @@ Build reliable CI/CD pipelines, debug deployment failures quickly, and ensure ev 18.16.0 # CI config (.github/workflows/deploy.yml) -- uses: actions/setup-node@v3 +- uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: node-version-file: '.node-version' ``` @@ -112,7 +112,7 @@ main: run: npm audit --audit-level=high - name: Secret scanning - uses: trufflesecurity/trufflehog@main + uses: trufflesecurity/trufflehog@6c05c4a00b91aa542267d8e32a8254774799d68d # v3.93.8 ``` ## Step 4: Debugging Methodology @@ -209,7 +209,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - run: npm ci - run: npm test diff --git a/instructions/github-actions-ci-cd-best-practices.instructions.md b/instructions/github-actions-ci-cd-best-practices.instructions.md index 68a0224f7..d3e006833 100644 --- a/instructions/github-actions-ci-cd-best-practices.instructions.md +++ b/instructions/github-actions-ci-cd-best-practices.instructions.md @@ -47,9 +47,9 @@ jobs: artifact_path: ${{ steps.package_app.outputs.path }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - name: Setup Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: node-version: 18 - name: Install dependencies and build @@ -62,7 +62,7 @@ jobs: zip -r dist.zip dist echo "path=dist.zip" >> "$GITHUB_OUTPUT" - name: Upload build artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: my-app-build path: dist.zip @@ -74,7 +74,7 @@ jobs: environment: staging steps: - name: Download build artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: my-app-build - name: Deploy to Staging @@ -87,17 +87,17 @@ jobs: ### **3. Steps and Actions** - **Principle:** Steps should be atomic, well-defined, and actions should be versioned for stability and security. - **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. - **`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. - **`with`:** Provide inputs to actions. Ensure all required inputs are present. - **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 `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. -- **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 @@ -136,7 +136,7 @@ jobs: - **Federated Identity:** This is a key pattern for modern, secure cloud deployments. - **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. - - 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@ # v4.x.x`). Always pin to a full commit SHA. - 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. @@ -162,7 +162,7 @@ jobs: permissions: contents: read # This job only needs to read code, override workflow default steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - run: npm run lint ``` @@ -219,13 +219,13 @@ jobs: - **Restore Keys:** Use `restore-keys` for fallbacks to older, compatible caches. - **Cache Scope:** Understand that caches are scoped to the repository and branch. - **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. - Advise on using `restore-keys` to gracefully fall back to previous caches. - **Example (Advanced Caching for Monorepo):** ```yaml - name: Cache Node.js modules - uses: actions/cache@v3 + uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 with: path: | ~/.npm @@ -259,8 +259,8 @@ jobs: node-version: [16.x, 18.x, 20.x] browser: [chromium, firefox] steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v3 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + - uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: node-version: ${{ matrix.node-version }} - name: Install Playwright browsers @@ -289,7 +289,7 @@ jobs: - **`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. - **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). - 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. @@ -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. - **Limitations:** Artifacts are immutable once uploaded. Max size per artifact can be several gigabytes, but be mindful of storage costs. - **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. - 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. @@ -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 `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 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 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?