> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub Actions Pinning and Security

> Secure your package's supply chain by pinning GitHub Actions dependencies to commit SHAs instead of version tags. Learn Dependabot configuration and automated update strategies used by official Laravel projects.

To defend against attacks and tampering of GitHub Actions, the official Laravel projects implement a critical security measure: pinning Action dependencies to commit hashes. This page explains the practical approach package developers should adopt.

<Info>
  This page is a companion to [Package Development Basics](/en/advanced/package-development). It assumes you're familiar with GitHub Actions basics.
</Info>

## Security Risks of GitHub Actions

### Dangers of Tag-Based References

Most GitHub Actions are referenced by tags:

```yaml theme={null}
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
```

Problems with this approach:

* **Tags are mutable** — Tags can be deleted and recreated with the same name
* **Tampering risk** — If an action's repository owner is compromised, malicious code can be injected
* **Supply chain attacks** — If a dependency is attacked, your workflow becomes vulnerable

### How Official Laravel Projects Respond

[laravel/laravel](https://github.com/laravel/laravel) and [laravel/framework](https://github.com/laravel/framework) pin all actions to full commit hashes (SHAs).

```yaml theme={null}
# Secure reference method
- uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
```

## Implementation Strategy

### Step 1: Create Dependabot Configuration

Create `.github/dependabot.yml` in your repository. You can copy Laravel's file directly:

```yaml theme={null}
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"
    cooldown:
      default-days: 5
    groups:
      github-actions:
        patterns:
          - "*"
```

This file:

* **Scans automatically** — Detects new GitHub Action versions
* **Creates update PRs** — Proposes changes when updates are available
* **Controls update method** — Unpinned actions update by version; pinned actions update by SHA

### Step 2: Pin Existing Actions to SHAs

Convert all action references in your workflows to commit hashes. Use [pinact](https://github.com/suzuki-shunsuke/pinact) to automate this.

#### Using the pinact Tool

```shell theme={null}
# Pin all actions to SHAs
pinact run
```

#### Manual Approach

If `pinact` is unavailable, look up commit SHAs on each action's [latest version page](https://github.com/actions/checkout) and update manually:

```yaml theme={null}
# Before
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
  with:
    php-version: ${{ matrix.php }}

# After
- uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
- uses: shivammathur/setup-php@0a92e4568cab5c87b7175192630661408458a086  # v2
  with:
    php-version: ${{ matrix.php }}
```

### Step 3: Enable Dependabot Configuration

Commit and push `.github/dependabot.yml` to your repository. Dependabot will automatically begin scanning.

## How Dependabot Updates Work

Dependabot applies different update strategies based on your `dependabot.yml` configuration:

### Unpinned Actions

```yaml theme={null}
# Before pinning
- uses: actions/checkout@v4
```

Dependabot's update: **Updates the version range to a new version**

```yaml theme={null}
# PR created by Dependabot
- uses: actions/checkout@v5
```

This prioritizes convenience and handles tag movement, but security risks remain.

### Pinned Actions

```yaml theme={null}
# After pinning
- uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
```

Dependabot's update: **Updates the commit hash to the new version's hash**

```yaml theme={null}
# PR created by Dependabot
- uses: actions/checkout@f1d3225b54b677ba3e72df8c464cb6cf6dc1aebf  # v4
```

This is the most secure approach. Even with new versions, SHA references protect against tampering.

## Complete Workflow Example

A comprehensive example using multiple actions:

```yaml theme={null}
name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    
    strategy:
      fail-fast: false
      matrix:
        php: [8.2, 8.3, 8.4]
        laravel: ["^12.0", "^13.0"]

    steps:
      - uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4
        with:
          fetch-depth: 0

      - name: Setup PHP
        uses: shivammathur/setup-php@0a92e4568cab5c87b7175192630661408458a086  # v2
        with:
          php-version: ${{ matrix.php }}
          extensions: dom, curl, libxml, mbstring, zip, intl, sqlite3
          coverage: none

      - name: Install dependencies
        run: |
          composer require "laravel/framework:${{ matrix.laravel }}" \
                           --no-interaction --no-update
          composer update --prefer-dist --no-interaction

      - name: Run tests
        run: vendor/bin/pest

  lint:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@a5ac7e51b41094c7fcab2042361574b0021804ab  # v4

      - name: Setup PHP
        uses: shivammathur/setup-php@0a92e4568cab5c87b7175192630661408458a086  # v2
        with:
          php-version: "8.4"
          extensions: dom, curl, libxml, mbstring, zip
          coverage: none

      - name: Install dependencies
        run: composer install --prefer-dist --no-interaction

      - name: Run static analysis
        run: vendor/bin/phpstan
```

## Responding to Dependabot Update PRs

Handle Dependabot's automated update PRs appropriately:

### Single Action Updates

```
Bump shivammathur/setup-php from v1 to v2
```

For straightforward updates:

1. Review workflow execution results
2. Check for breaking changes
3. Merge and close

### Security Update PRs

```
[SECURITY] Bump actions/checkout to a5ac7e51b41094c7fcab2042361574b0021804ab
```

Prioritize security fixes and merge immediately.

### Grouped Multi-Action Updates

With `groups` configured in `dependabot.yml`, multiple actions update in a single PR:

```yaml theme={null}
groups:
  github-actions:
    patterns:
      - "*"
```

Grouping reduces merge overhead.

## Benefits and Tradeoffs

### Benefits

| Benefit                     | Description                                                      |
| --------------------------- | ---------------------------------------------------------------- |
| **Supply chain protection** | References specific commit hashes, resistant to action tampering |
| **Auditability**            | Track exactly when and to what version each action was updated   |
| **Explicit updates**        | Dependabot requires human review before changes                  |
| **Reproducibility**         | Same commit hash = identical environment every run               |

### Tradeoffs

| Tradeoff                 | Solution                                          |
| ------------------------ | ------------------------------------------------- |
| **Initial manual setup** | Use `pinact` for automation                       |
| **Update overhead**      | Dependabot automates PR creation, minimizing work |
| **Readability**          | Include version in comments for clarity           |

## Security Audit Checklist

Use this checklist when starting a new package project:

<AccordionGroup>
  <Accordion title="Initial Setup">
    * [ ] Create `.github/dependabot.yml`
    * [ ] Pin all existing actions to SHA
    * [ ] Verify with `pinact` or manually
    * [ ] Confirm workflows execute successfully
  </Accordion>

  <Accordion title="Ongoing Maintenance">
    * [ ] Review Dependabot update PRs weekly
    * [ ] Prioritize security updates for immediate merge
    * [ ] Pin new actions to SHA when added
    * [ ] Monthly: Review all workflow status
  </Accordion>

  <Accordion title="Audit">
    * [ ] All action references are SHA-based
    * [ ] Dependabot is enabled
    * [ ] Last 6 months of Dependabot PRs are merged
  </Accordion>
</AccordionGroup>

## Related Pages

<Columns cols={2}>
  <Card title="Package Development Basics" icon="box" href="/en/advanced/package-development">
    Learn about Laravel package development with service providers at the core.
  </Card>

  <Card title="Package Version Compatibility" icon="tag" href="/en/advanced/package-versioning">
    Explore strategies for supporting multiple Laravel versions in your package.
  </Card>
</Columns>
