As a PHP developer, you’ve likely encountered the jarring experience of discovering a security vulnerability in your application’s dependencies. Maybe it was during a code review, or worse, after an attacker had already exploited the issue. You may have spent hours digging through stack traces and online forums to identify the root cause, only to realize that the fix requires a painful manual update process.
You’ll build on this experience by learning how to automate security checks and updates for your Laravel application using GitHub Actions and Dependabot. By the end of this tutorial, you’ll have set up a workflow that integrates the ZAP security scanner to scan your running application for vulnerabilities, and will be able to automatically update dependencies with critical patches – freeing yourself from the drudgery of manual dependency management.
Prerequisites: Setting Up a Laravel Project with GitHub
Before we dive into securing your PHP application using GitHub Actions and Dependabot, you’ll need to set up a new Laravel project on GitHub. This will allow us to configure Dependabot and create a workflow for automated security checks.
First, create a new directory for your project and navigate to it in your terminal:
mkdir my-laravel-project
cd my-laravel-project
Next, run the following command to create a new Laravel project using Composer:
composer create-project --prefer-dist laravel/laravel .
This will install Laravel in the current directory.
Now that we have our Laravel project set up, let’s create a new Git repository on GitHub. Create a new account or sign in if you already have one, then click the “+” button to create a new repository:
- Name your repository something like
my-laravel-project - Set the repository visibility to “Public”
- Click “Create repository”
Once the repository is created, navigate back to your terminal and link your local project with the GitHub repository:
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/your-username/my-laravel-project.git
git push -u origin main
Replace https://github.com/your-username/my-laravel-project.git with the actual URL of your repository.
Configuring Dependabot for Vulnerability Scanning and Alerts
To take advantage of Dependabot’s vulnerability scanning and alert features, we need to configure it in our GitHub repository.
First, navigate to your repository settings on GitHub and, in the “Security” section of the left-hand menu, click on “Advanced Security” (called “Code security” on some older GitHub interfaces). In the “Dependabot” section, click “Enable” next to “Dependabot alerts” if you haven’t already.
Once enabled, also click “Enable” next to “Dependabot security updates”. Dependabot detects your composer.lock file automatically, so it will open pull requests for vulnerable Composer packages in your Laravel project. To also tell Dependabot which package ecosystem to check for regular version updates, we’ll set up a .github/dependabot.yml configuration file in our repository.
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "daily"
This configuration tells Dependabot to check for updates daily. The package-ecosystem key tells Dependabot which package manager to use (in this case, Composer), and directory points to the location of your composer.json and composer.lock files (the repository root). With these settings in place, Dependabot will start scanning our dependencies for vulnerabilities and alerting us when necessary.
Setting Up GitHub Actions to Run Security Checks on Pull Requests
Now that Dependabot is configured and vulnerability scanning is enabled, it’s time to integrate our Laravel project with GitHub Actions. This will allow us to run security checks automatically whenever a new pull request is submitted.
First, let’s navigate to our repository in the browser and click on the “Actions” tab. Then, we’ll create a new workflow by clicking the “New workflow” button and choosing “set up a workflow yourself”.
# .github/workflows/security-checks.yml
name: Security Checks
on:
pull_request:
branches:
- main
jobs:
composer-audit:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
tools: composer:v2
- name: Install dependencies
run: composer install --prefer-dist --no-interaction --no-progress
- name: Run security checks
run: |
composer validate
composer audit
In this example workflow, we’re specifying that the job should run on pull requests targeting our main branch. The composer-audit job consists of four steps: checking out the code, setting up PHP and Composer, installing dependencies with Composer, and running security checks using composer validate and composer audit, which checks your installed packages against known security advisories and fails the job if any vulnerable versions are found.
Once saved, GitHub Actions will automatically trigger a new workflow whenever a new pull request is submitted, ensuring our project’s dependencies are up-to-date and secure. This concludes our setup of Dependabot and GitHub Actions for vulnerability scanning and automated dependency updates.
Integrating the ZAP Security Scanner into Your GitHub Actions Workflow
In this section, we’ll explore how to integrate ZAP (Zed Attack Proxy, formerly OWASP ZAP) into our GitHub Actions workflow. ZAP is a popular open-source web application security scanner that can help identify vulnerabilities in our running Laravel application.
First, let’s create a .github/workflows/zap-scan.yml file that starts our Laravel application and runs the official ZAP baseline scan action against it:
# .github/workflows/zap-scan.yml
name: Security Scan
on:
pull_request:
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- name: Start Laravel application
run: |
composer install --prefer-dist --no-interaction --no-progress
cp .env.example .env
php artisan key:generate
touch database/database.sqlite
php artisan migrate --force
php artisan serve --host=0.0.0.0 --port=8000 &
sleep 5
- name: Run ZAP baseline scan
uses: zaproxy/action-baseline@v0.15.0
with:
target: 'http://localhost:8000'
allow_issue_writing: false
This workflow will start our Laravel application on port 8000, spin up a ZAP container, and then run the baseline vulnerability scanner against our Laravel application.
To view the results of the scan, navigate to your GitHub repository’s Actions page. Click on the most recent “Security Scan” workflow run and open the scan job. In the logs, you should see a detailed report highlighting any potential vulnerabilities found by ZAP, and the full report is also attached to the run as a zap_scan artifact.
With this integration in place, we’ll be able to catch security issues early in our development cycle and ensure our application is safer for users.
Automating Dependency Updates with Dependabot Auto-Merge
In our previous sections, we’ve set up GitHub Actions to run security checks on pull requests and integrated the ZAP scanner into our workflow. However, vulnerabilities can still arise from outdated dependencies. To mitigate this risk, we’ll automatically merge Dependabot’s patch-level update pull requests once they pass our checks.
To configure auto-merging, navigate to your repository’s settings in the GitHub web interface, stay on the “General” page, and under “Pull Requests” enable “Allow auto-merge”. Then add a branch protection rule for main that requires the composer-audit and scan status checks to pass, so nothing is merged before the security checks succeed. Next, create a new file named .github/workflows/dependabot-auto-merge.yml with the following contents:
# .github/workflows/dependabot-auto-merge.yml
name: Dependabot auto-merge
on: pull_request
permissions:
contents: write
pull-requests: write
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.event.pull_request.user.login == 'dependabot[bot]'
steps:
- name: Fetch Dependabot metadata
id: metadata
uses: dependabot/fetch-metadata@v2
with:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Enable auto-merge for patch updates
if: steps.metadata.outputs.update-type == 'version-update:semver-patch'
run: gh pr merge --auto --squash "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
This workflow reads the metadata of each Dependabot pull request and enables auto-merge for patch-level updates, so they are merged automatically as soon as all required checks pass.
Once configured, Dependabot will automatically create pull requests to update vulnerable dependencies. If you want to exclude specific packages or versions from these updates, you can modify the .github/dependabot.yml file accordingly. For instance:
version: 2
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "daily"
ignore:
- dependency-name: "monolog/monolog"
versions: ["2.x"]
This example excludes Monolog version 2.x from Dependabot updates.
By automating dependency updates, you ensure your application stays secure and up-to-date with the latest dependencies. With this final step, our GitHub Actions workflow is now fully integrated with Dependabot’s security features.
Frequently Asked Questions
How do I set up Dependabot for my Laravel project on GitHub?
To configure Dependabot, navigate to your repository settings on GitHub and click ‘Advanced Security’ in the ‘Security’ section of the left-hand menu. Enable ‘Dependabot alerts’ and ‘Dependabot security updates’, then add a .github/dependabot.yml file for version updates.
What is the difference between using Dependabot and manually updating dependencies?
Using Dependabot automates security checks and updates for your dependencies, freeing you from manual dependency management. It also provides alerts for potential vulnerabilities and opens pull requests that patch vulnerable packages, which you can merge automatically with a GitHub Actions workflow.
How do I configure a workflow in GitHub Actions to integrate the ZAP scanner?
To set up a workflow that integrates ZAP, open your repository’s ‘Actions’ tab on GitHub, click on ‘New workflow’, choose ‘set up a workflow yourself’, and add a job that starts your Laravel application and runs the zaproxy/action-baseline action against it.
What is the purpose of the .github/dependabot.yml configuration file in my repository?
The .github/dependabot.yml configuration file specifies which package ecosystems Dependabot should check for version updates, where their manifest files live, and how often to check. For this example, we set it up to use composer for Laravel projects.
What happens if I forget to update a dependency with a critical patch using Dependabot?
If you forget to update a dependency with a critical patch using Dependabot, the Dependabot alert stays open on your repository’s Security tab and the composer audit step in your workflow will fail until the vulnerability is resolved. You can then manually update the dependency or allow Dependabot to automate the patching process.
