mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-23 09:35:13 +00:00
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:
2
.github/workflows/check-line-endings.yml
vendored
2
.github/workflows/check-line-endings.yml
vendored
@@ -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: |
|
||||||
|
|||||||
4
.github/workflows/check-plugin-structure.yml
vendored
4
.github/workflows/check-plugin-structure.yml
vendored
@@ -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');
|
||||||
|
|||||||
2
.github/workflows/check-pr-target.yml
vendored
2
.github/workflows/check-pr-target.yml
vendored
@@ -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 = [
|
||||||
|
|||||||
4
.github/workflows/codespell.yml
vendored
4
.github/workflows/codespell.yml
vendored
@@ -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
|
||||||
|
|||||||
6
.github/workflows/contributors.yml
vendored
6
.github/workflows/contributors.yml
vendored
@@ -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"
|
||||||
|
|||||||
2
.github/workflows/copilot-setup-steps.yml
vendored
2
.github/workflows/copilot-setup-steps.yml
vendored
@@ -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:
|
||||||
|
|||||||
10
.github/workflows/deploy-website.yml
vendored
10
.github/workflows/deploy-website.yml
vendored
@@ -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
|
||||||
|
|||||||
4
.github/workflows/publish.yml
vendored
4
.github/workflows/publish.yml
vendored
@@ -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 }}
|
||||||
|
|
||||||
|
|||||||
@@ -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: |
|
||||||
|
|||||||
6
.github/workflows/validate-readme.yml
vendored
6
.github/workflows/validate-readme.yml
vendored
@@ -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: |
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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?
|
||||||
|
|||||||
Reference in New Issue
Block a user