Skip to content

- ci: add minimum required permissions to GitHub Actions workflows#159

Merged
mtracz merged 2 commits intomainfrom
copilot/fix-github-actions-permissions
Mar 26, 2026
Merged

- ci: add minimum required permissions to GitHub Actions workflows#159
mtracz merged 2 commits intomainfrom
copilot/fix-github-actions-permissions

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 25, 2026

All four workflows were missing explicit permissions blocks, leaving them with GitHub's overly-permissive defaults. This adds least-privilege permissions at the top level of each workflow.

Changes

  • check-php.ymlcontents: read (PR lint/test, read-only)
  • title.ymlcontents: read + pull-requests: read (needs PR metadata for title check)
  • deploy-to-dev.ymlcontents: read (SSH deploy to external registry, no GITHUB_TOKEN writes)
  • deploy-to-production.ymlcontents: read (same as dev)
permissions:
  contents: read
Original prompt

Goal

Audit and fix all GitHub Actions workflows in .github/workflows/ by adding explicit permissions blocks with the minimum required permissions. This follows the security best practice of least-privilege (principle of minimal permissions). Also fix any other security issues found.

Security principles to apply

  1. Add permissions: read-all at the top-level as a global default deny-all (or better: permissions: {} which sets everything to none), then grant only what each job truly needs.
  2. Alternatively, add per-job permissions blocks with only what that job needs.
  3. Never leave workflows without explicit permissions — the default is overly permissive (write-all on private repos, or broad on public repos without top-level restriction).
  4. Use pinned actions by SHA (already done in most workflows — keep them).
  5. Do NOT add GITHUB_TOKEN write permissions unless strictly required.

Workflows to fix

.github/workflows/check-php.yml

  • Trigger: pull_request only — reads code, runs tests/lint, no writes needed.
  • Add top-level:
    permissions:
      contents: read

.github/workflows/title.yml

  • Trigger: pull_request — checks PR title using blumilksoftware/action-pr-title.
  • This action needs to read PR metadata. It may need pull-requests: read.
  • Add top-level:
    permissions:
      contents: read
      pull-requests: read

.github/workflows/deploy-to-dev.yml

  • Trigger: workflow_dispatch — deploys via SSH, builds/pushes Docker images to an external registry (not GHCR), fetches secrets from Infisical. No GITHUB_TOKEN write needed.
  • Add top-level:
    permissions:
      contents: read

.github/workflows/deploy-to-production.yml

  • Trigger: workflow_dispatch with tag input — same pattern as deploy-to-dev.
  • Add top-level:
    permissions:
      contents: read

Current file contents for reference

check-php.yml (BlobSha: 4603c26a3800a3013b3d51f03e95b837289574d8)

name: "Checking app: testing and linting PHP"

on:
  pull_request:
    branches: [ "main" ]
    types: [opened, synchronize, reopened, ready_for_review]
    paths:
      - '**.php'
      - 'composer.json'
      - 'composer.lock'
      - 'phpunit.xml'
      - 'env.ci'

jobs:
  test-and-lint-php:
    name: Test & lint PHP codebase
    timeout-minutes: 10
    if: github.event.pull_request.draft == false
    runs-on: ubuntu-latest
    services:
      pgsql:
        image: postgres:16.3-alpine3.18@sha256:64e18e8fb3e9c9aac89ac590c5dd8306b862478404f76cd9b5f7720d012b4c47
        env:
          POSTGRES_DB: lmt-ci
          POSTGRES_USER: lmt-ci
          POSTGRES_PASSWORD: password
        options: >-
          --health-cmd pg_isready
          --health-interval 3s
          --health-timeout 3s
          --health-retries 5
        ports:
          - 5432:5432

    steps:
      - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 # https://github.com/actions/checkout

      - name: Validate composer.json and composer.lock
        run: composer validate

      - name: Cache dependencies
        uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4 # https://github.com/actions/cache
        with:
          path: vendor
          key: ${{ runner.os }}-composer-dependencies-${{ hashFiles('composer.lock') }}
          restore-keys: ${{ runner.os }}-composer-dependencies

      - name: Setup PHP
        uses: shivammathur/setup-php@bf6b4fbd49ca58e4608c9c89fba0b8d90bd2a39f # 2.35.5 # https://github.com/shivammathur/setup-php
        with:
          php-version: 8.3
          extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, pdo_pgsql, intl
          coverage: none

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

      - name: Run PHP linter
        run: composer cs

      - name: Execute tests
        run: php artisan test --env=ci

title.yml (BlobSha: 788b29aca177ca3463ac52fd807a091fa879494e)

name: "Check the PR title"

on:
  pull_request:
    branches:
      - main
    types:
      - opened
      - edited
      - synchronize

jobs:
  check-pr-title:
    name: Check the PR title
    runs-on: ubuntu-24.04
    steps:
      - uses: blumilksoftware/action-pr-title@e05fc76a1cc45b33644f1de51218be43ac121dd0 # v1.2.0

deploy-to-dev.yml (BlobSha: 9acba3d4e5ea8e68f613c33774318091eff3442c)

Current content is 169 lines, deploying to dev via SSH. No GITHUB_TOKEN writes needed. Add permissions: contents: read at top level.

deploy-to-production.yml (BlobSha: 5ee9d1568d6d9a757f6cca896344e9f8f2191c9d)

Current content is 166 lines, deploying to production via SSH. No GITHUB_TOKEN writes needed. Add permissions: contents: read at top level.

Instructions

  • Edit all 4 workflow files.
  • Add the permissions block right after the on: block and before jobs: (or at top level before jobs:...

This pull request was created from Copilot chat.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI changed the title [WIP] Audit and fix GitHub Actions workflows by adding permissions ci: add minimum required permissions to GitHub Actions workflows Mar 25, 2026
Copilot AI requested a review from mtracz March 25, 2026 13:32
@mtracz mtracz changed the title ci: add minimum required permissions to GitHub Actions workflows - ci: add minimum required permissions to GitHub Actions workflows Mar 25, 2026
@mtracz mtracz marked this pull request as ready for review March 25, 2026 13:34
@mtracz mtracz requested a review from a team as a code owner March 25, 2026 13:34
@mtracz mtracz merged commit 505e6ff into main Mar 26, 2026
4 checks passed
@mtracz mtracz deleted the copilot/fix-github-actions-permissions branch March 26, 2026 08:18
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.

3 participants