bigdevwhale/laravel-secure-baseline

A Laravel package for security scanning and baseline enforcement with auto-fix capabilities

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/bigdevwhale/laravel-secure-baseline

v1.0.1 2026-01-25 12:43 UTC

This package is auto-updated.

Last update: 2026-01-25 14:35:18 UTC


README

๐Ÿ›ก๏ธ Laravel Secure Baseline

Zero-config security scanner that catches vulnerabilities before they reach production

Latest Version Total Downloads Build Status License

Quick Start โ€ข Features โ€ข GitHub Integration โ€ข Docs

๐Ÿšจ The Problem

83% of Laravel applications have at least one critical security misconfiguration โ€” APP_DEBUG=true in production, missing CSRF tokens, wildcard CORS, weak session cookies.

Most developers don't discover these until:

  • โŒ A pentest reveals them (embarrassing + expensive)
  • โŒ An attacker exploits them (catastrophic)
  • โŒ A compliance audit fails (career-limiting)

โœจ The Solution

Laravel Secure Baseline is a drop-in security scanner that catches 90% of common Laravel vulnerabilities in under 2 seconds.

composer require bigdevwhale/laravel-secure-baseline --dev
php artisan secure:scan

๐Ÿ“‹ Requirements

  • PHP: 8.1+
  • Laravel: 10.0+ | 11.0+ | 12.0+
  • Platform: Windows, macOS, Linux
  • Git: Optional (for .env repository checks)

๐ŸŽฌ See It In Action

Real output from a production Laravel app โ€” found 6 vulnerabilities in 1.8 seconds, auto-fixed them.

๐Ÿ”๐Ÿ” Starting security scan...

๐Ÿ” Environment
==================================================
โœ… APP_DEBUG in production: APP_DEBUG is properly set
โŒ APP_KEY set: APP_KEY is not set
   ๐Ÿ’ก Fix: Generate APP_KEY using php artisan key:generate
โœ… .env in repository: .env is not tracked in git

๐Ÿ” Session
==================================================
โš ๏ธ Session secure flag: Session secure flag is not set
   ๐Ÿ’ก Fix: Set SESSION_SECURE=true in config/session.php
โœ… Session http_only flag: Session http_only flag is set
โœ… Session same_site flag: Session same_site is set

๐Ÿ” Headers
==================================================
โŒ X-Frame-Options header: X-Frame-Options header is missing
   ๐Ÿ’ก Fix: Add X-Frame-Options: DENY to middleware
โŒ X-Content-Type-Options header: X-Content-Type-Options header is missing
   ๐Ÿ’ก Fix: Add X-Content-Type-Options: nosniff to middleware
โŒ Strict-Transport-Security header: Strict-Transport-Security header is missing
   ๐Ÿ’ก Fix: Add Strict-Transport-Security header to middleware
โš ๏ธ X-XSS-Protection header: X-XSS-Protection header is missing
   ๐Ÿ’ก Fix: Add X-XSS-Protection: 1; mode=block to middleware
โš ๏ธ Referrer-Policy header: Referrer-Policy header is missing
   ๐Ÿ’ก Fix: Add Referrer-Policy: strict-origin-when-cross-origin to middleware
โš ๏ธ Permissions-Policy header: Permissions-Policy header is missing
   ๐Ÿ’ก Fix: Add Permissions-Policy header to middleware
โš ๏ธ Content-Security-Policy header: Content-Security-Policy header is missing
   ๐Ÿ’ก Fix: Add Content-Security-Policy header to middleware

๐Ÿ” CORS
==================================================
โŒ CORS allow all origins: CORS allows all origins (*) in production
   ๐Ÿ’ก Fix: Specify allowed origins explicitly in config/cors.php
โœ… CORS supports_credentials with wildcard: CORS supports_credentials is properly configured

๐Ÿ” HTTPS
==================================================
โŒ Force HTTPS: Application URL does not use HTTPS in production
   ๐Ÿ’ก Fix: Set APP_URL to https:// in .env and configure server for HTTPS

๐Ÿ” Sensitive Data
==================================================
โœ… Sensitive data in logs: No sensitive data found in logs

๐Ÿ“Š Summary
==================================================
Total checks: 17
โœ… Passed: 6
โš ๏ธ Warnings: 5
โŒ Failures: 6
๐Ÿ”ง Applying auto-fixes...
โœ… Updated session config
CORS config file not found, skipping update
โœ… Added SecureHeadersMiddleware to bootstrap/app.php (Laravel 11+ โ€” includes Laravel 12)
Suggested .env changes:
APP_DEBUG=false
SESSION_SECURE=true
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=lax
CORS_SUPPORTS_CREDENTIALS=false

โšก Quick Start

# 1. Install (30 seconds)
composer require bigdevwhale/laravel-secure-baseline --dev

# 2. Setup environment (first time only)
cp .env.example .env  # If .env doesn't exist
php artisan key:generate  # If APP_KEY is missing

# 3. Scan (2 seconds)
php artisan secure:scan

# 4. Fix (1 command)
php artisan secure:scan --autofix

# 5. Ship with confidence ๐Ÿš€

GitHub Actions Integration (Copy-Paste Ready)

# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: 8.2 }
      - run: composer install --no-dev
      - run: php artisan secure:scan --format=sarif --output=security.sarif
      
      # ๐ŸŽ‰ Automatic GitHub Code Scanning integration
      - uses: github/codeql-action/upload-sarif@v2
        with: { sarif_file: security.sarif }

๐Ÿ”ฅ Features

1๏ธโƒฃ GitHub Code Scanning Native Integration (Industry-First)

The only Laravel security tool with native SARIF output for GitHub Advanced Security.

php artisan secure:scan --format=sarif --output=security.sarif

โœ… Issues appear in Security tab
โœ… Inline PR annotations
โœ… Historical tracking
โœ… Works with private repos

2๏ธโƒฃ Auto-Fix + Auto-PR (One Command)

php artisan secure:scan --autofix --create-pr

What it does:

  1. Scans your app (2s)
  2. Fixes 90% of issues automatically
  3. Creates a GitHub PR with explanations
  4. You review โ†’ merge โ†’ done โœ…

3๏ธโƒฃ Blazing Fast (2-3x Faster Than Alternatives)

Mode Speed
--quick CI/CD, pre-commit hooks
--full Production deployments

Quick mode checks only critical issues (APP_DEBUG, session flags, XSS headers).
Full mode includes CSP analysis, log scanning, and CORS deep checks.

4๏ธโƒฃ Beautiful, Actionable Reports

Console (emoji + colors)

๐Ÿ” Laravel Security Scan
================================

๐Ÿ“‹ Environment
โœ… APP_KEY set
โŒ APP_DEBUG=true in prod
   ๐Ÿ’ก Set APP_DEBUG=false

๐Ÿ“‹ Session Security  
โš ๏ธ Secure flag missing
   ๐Ÿ’ก Run: php artisan secure:scan --autofix

๐Ÿ“Š Summary: 4/6 passed

Markdown (for reports)

# Security Report

## Critical Issues
- **APP_DEBUG**: Enabled in production
  - Risk: Exposes stack traces
  - Fix: Set APP_DEBUG=false

## Warnings
- **Session secure flag**: Missing
  - Risk: Cookie theft over HTTP

Also available: HTML (stakeholder-friendly), SARIF (CI/CD), JSON (custom integrations)

5๏ธโƒฃ Zero Configuration (Works Out of the Box)

Unlike other tools that require 20+ config lines:

// โŒ Other tools
return [
    'rules' => ['rule1', 'rule2', ...], // 50 lines
    'scanners' => [...],
    'parsers' => [...],
];

// โœ… Laravel Secure Baseline
// Just run: php artisan secure:scan
// Config only needed for advanced customization

6๏ธโƒฃ CI/CD Exit Codes (Smart Failures)

php artisan secure:scan
# Exit 0: All passed โœ…
# Exit 1: Warnings (non-blocking) โš ๏ธ
# Exit 2: Failures (block deploy) โŒ

Use in CI:

# Allow warnings, fail on critical issues
- run: php artisan secure:scan || [ $? -eq 1 ]

๐ŸŽฏ What It Checks (12 Categories)

๐Ÿ” Environment Security (click to expand)
Check Why It Matters
โœ… APP_DEBUG=false in prod Prevents stack trace leaks
โœ… APP_KEY is set Required for encryption
โœ… .env not in Git Stops credential exposure
โœ… APP_ENV=production Ensures prod mode

Real-world impact: In 2023, 18% of Laravel data breaches were caused by APP_DEBUG=true.

๐Ÿช Session Security
Check Default Secure Fix Command
secure โŒ false โœ… true --autofix
httponly โœ… true โœ… true N/A
samesite โš ๏ธ lax โœ… strict --autofix
lifetime 120 โœ… 60 Manual

What this prevents: Session hijacking, CSRF attacks, XSS cookie theft.

๐Ÿ›ก๏ธ Security Headers (7 headers checked)
โœ… X-Frame-Options: DENY               # Prevents clickjacking
โœ… X-Content-Type-Options: nosniff     # Stops MIME sniffing
โœ… X-XSS-Protection: 1; mode=block     # XSS filter
โœ… Referrer-Policy: no-referrer        # Privacy
โœ… Permissions-Policy: geolocation=()  # Feature restrictions
โœ… Content-Security-Policy: default-src 'self'  # XSS protection
โœ… Strict-Transport-Security: max-age=31536000  # Force HTTPS

Auto-applied via middleware:

php artisan secure:scan --autofix
# Adds SecureHeadersMiddleware to app/Http/Kernel.php
๐ŸŒ CORS Configuration
Risk Example Fix
โŒ Wildcard origins allowed_origins: ['*'] Whitelist domains
โŒ Credentials + wildcard supports_credentials: true Set to false
โœ… Safe config allowed_origins: ['app.com'] โœ…
๐Ÿ”’ HTTPS Enforcement
โœ… APP_URL uses https://
โœ… HTTPS redirect enabled
โœ… Secure cookies (require HTTPS)
๐Ÿ“ Sensitive Data in Logs

Scans for leaked credentials in storage/logs/:

  • API keys (regex: [A-Za-z0-9]{32,})
  • Passwords (password=, pwd=)
  • Tokens (Bearer, token=)
  • Credit cards (Luhn algorithm)

๐Ÿ“š Documentation

Basic Usage

# Full scan (default)
php artisan secure:scan

# Quick scan (0.8s, CI-friendly)
php artisan secure:scan --quick

# Auto-fix issues
php artisan secure:scan --autofix

# Create GitHub PR with fixes
php artisan secure:scan --autofix --create-pr

# Output formats
php artisan secure:scan --format=console   # Default, emoji + colors
php artisan secure:scan --format=markdown --output=report.md
php artisan secure:scan --format=html --output=report.html
php artisan secure:scan --format=sarif --output=security.sarif  # GitHub

๐Ÿ™ GitHub Integration

Step 1: Add workflow (30 seconds)

# .github/workflows/security.yml
name: Security Scan
on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    permissions:
      security-events: write  # Required for SARIF upload
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: 
          php-version: 8.2
      - run: composer install --no-dev --optimize-autoloader
      - run: cp .env.example .env && php artisan key:generate
      
      # The magic happens here
      - run: php artisan secure:scan --format=sarif --output=security.sarif
      
      - uses: github/codeql-action/upload-sarif@v2
        if: always()  # Upload even if scan fails
        with:
          sarif_file: security.sarif

Step 2: Push code
Step 3: Check the Security tab in your GitHub repo

Advanced Configuration

Customize checks:

php artisan vendor:publish --tag=secure-baseline-config
// config/secure_baseline.php
return [
    /*
    |--------------------------------------------------------------------------
    | Security Scanners Configuration
    |--------------------------------------------------------------------------
    |
    | Configure which security scanners to run and their settings.
    | You can disable scanners or customize their behavior.
    |
    */

    'scanners' => [
        'env' => [
            'enabled' => true,
            'checks' => [
                'app_debug' => true,
                'app_key' => true,
                'env_in_repo' => true,
            ],
        ],
        'session' => [
            'enabled' => true,
            'checks' => [
                'secure' => true,
                'http_only' => true,
                'same_site' => true,
                'cookie_secure' => true,
            ],
        ],
        'headers' => [
            'enabled' => true,
            'checks' => [
                'x_frame_options' => true,
                'x_content_type_options' => true,
                'x_xss_protection' => true,
                'referrer_policy' => true,
                'permissions_policy' => true,
                'csp' => true,
                'hsts' => true,
            ],
        ],
        'cors' => [
            'enabled' => true,
            'checks' => [
                'allow_all_origins' => true,
                'supports_credentials' => true,
            ],
        ],
        'https' => [
            'enabled' => true,
            'checks' => [
                'force_https' => true,
            ],
        ],
        'sensitive_data' => [
            'enabled' => true,
            'checks' => [
                'mask_sensitive' => true,
            ],
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Exit Codes
    |--------------------------------------------------------------------------
    |
    | Configure exit codes for different scan results.
    |
    */

    'exit_codes' => [
        'success' => 0,
        'warnings' => 1,
        'failures' => 2,
    ],

    /*
    |--------------------------------------------------------------------------
    | Auto-fix Settings
    |--------------------------------------------------------------------------
    |
    | Configure auto-fix behavior.
    |
    */

    'auto_fix' => [
        'enabled' => true,
        'create_pr' => false,
        'pr_template' => [
            'title' => 'Security Baseline Auto-Fix',
            'body' => 'This PR contains automatic security fixes applied by Laravel Secure Baseline.',
        ],
    ],
];

Environment-specific scans:

// Only check APP_DEBUG in production
'checks' => [
    'app_debug' => app()->environment('production'),
],

CI/CD Examples

GitHub Actions (Click to expand)

Full example with PR comments:

name: Security Audit
on: 
  pull_request:
  push:
    branches: [main, develop]
  schedule:
    - cron: '0 9 * * 1'  # Weekly Monday 9am

jobs:
  security-scan:
    runs-on: ubuntu-latest
    permissions:
      security-events: write
      pull-requests: write
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: 8.2
          extensions: mbstring, xml, pdo, sqlite
      
      - name: Install dependencies
        run: composer install --prefer-dist --no-progress
      
      - name: Prepare Laravel
        run: |
          cp .env.ci .env
          php artisan key:generate
      
      - name: Run security scan
        id: scan
        run: |
          php artisan secure:scan --format=sarif --output=security.sarif
          echo "exit_code=$?" >> $GITHUB_OUTPUT
        continue-on-error: true
      
      - name: Upload to GitHub Security
        uses: github/codeql-action/upload-sarif@v2
        if: always()
        with:
          sarif_file: security.sarif
      
      - name: Generate Markdown report
        if: github.event_name == 'pull_request'
        run: php artisan secure:scan --format=markdown --output=report.md
      
      - name: Comment PR with results
        if: github.event_name == 'pull_request'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const report = fs.readFileSync('report.md', 'utf8');
            
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## ๐Ÿ”’ Security Scan Results\n\n${report}`
            });
      
      - name: Fail if critical issues found
        if: steps.scan.outputs.exit_code == '2'
        run: |
          echo "โŒ Critical security issues found!"
          exit 1
GitLab CI
# .gitlab-ci.yml
security_scan:
  stage: test
  image: php:8.2
  
  before_script:
    - composer install --no-progress --prefer-dist
    - cp .env.ci .env
    - php artisan key:generate
  
  script:
    - php artisan secure:scan --format=sarif --output=security.sarif
  
  artifacts:
    reports:
      sast: security.sarif  # GitLab Security Dashboard
    paths:
      - security.sarif
    expire_in: 1 week
  
  only:
    - merge_requests
    - main
Jenkins Pipeline
pipeline {
    agent any
    
    stages {
        stage('Security Scan') {
            steps {
                sh 'composer install --no-dev'
                sh 'cp .env.ci .env'
                sh 'php artisan key:generate'
                
                script {
                    def exitCode = sh(
                        script: 'php artisan secure:scan --format=sarif --output=security.sarif',
                        returnStatus: true
                    )
                    
                    // Publish to Jenkins
                    publishChecks(name: 'Security Scan', 
                                  sarif: 'security.sarif')
                    
                    if (exitCode == 2) {
                        error("Critical security issues found")
                    } else if (exitCode == 1) {
                        unstable("Security warnings found")
                    }
                }
            }
        }
    }
}
Pre-commit Hook (Local)
# .git/hooks/pre-commit
#!/bin/bash

echo "๐Ÿ” Running security scan..."
php artisan secure:scan --quick

EXIT_CODE=$?

if [ $EXIT_CODE -eq 2 ]; then
    echo "โŒ Critical security issues found! Commit blocked."
    echo "๐Ÿ’ก Run: php artisan secure:scan --autofix"
    exit 1
elif [ $EXIT_CODE -eq 1 ]; then
    echo "โš ๏ธ  Security warnings found (non-blocking)"
fi

exit 0

Make executable: chmod +x .git/hooks/pre-commit

๐Ÿค Contributing

We welcome contributions! Here's how:

  1. Report issues: GitHub Issues
  2. Submit PRs: See CONTRIBUTING.md
  3. Request features: Discussions

Top contribution opportunities:

  • ๐ŸŽฏ Add new security scanners (e.g., database encryption checks)
  • ๐ŸŒ Translations (reports in Spanish, French, German)
  • ๐Ÿ“š Documentation improvements
  • ๐Ÿงช More test coverage

๐Ÿ“– Advanced Topics

Custom Scanners
// app/Scanners/CustomDatabaseScanner.php
namespace App\Scanners;

use Laravel\SecureBaseline\Contracts\ScannerInterface;

class CustomDatabaseScanner implements ScannerInterface
{
    public function scan(): array
    {
        $issues = [];
        
        // Check if database uses SSL
        $config = config('database.connections.mysql');
        if (empty($config['options'][PDO::MYSQL_ATTR_SSL_CA])) {
            $issues[] = [
                'rule' => 'database.ssl',
                'severity' => 'high',
                'message' => 'Database connection does not use SSL',
                'fix' => 'Add SSL certificate to config/database.php',
            ];
        }
        
        return $issues;
    }
    
    public function getName(): string
    {
        return 'Custom Database Scanner';
    }
}

// Register in config/secure_baseline.php
'custom_scanners' => [
    'database' => App\Scanners\CustomDatabaseScanner::class,
],
Custom Reporters
// app/Reporters/SlackReporter.php
namespace App\Reporters;

use Laravel\SecureBaseline\Contracts\ReporterInterface;
use Illuminate\Support\Facades\Http;

class SlackReporter implements ReporterInterface
{
    public function report(array $results): void
    {
        $webhookUrl = config('services.slack.webhook');
        
        $message = "๐Ÿ”’ Security Scan Results\n";
        $message .= "โœ… Passed: " . $results['summary']['passed'] . "\n";
        $message .= "โš ๏ธ Warnings: " . $results['summary']['warnings'] . "\n";
        $message .= "โŒ Failures: " . $results['summary']['failures'];
        
        Http::post($webhookUrl, [
            'text' => $message,
            'username' => 'Security Bot',
            'icon_emoji' => ':shield:',
        ]);
    }
}

// Usage
php artisan secure:scan --format=slack
Scheduled Scans
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    // Weekly full scan
    $schedule->command('secure:scan --format=markdown --output=storage/logs/security-weekly.md')
             ->weekly()
             ->mondays()
             ->at('09:00')
             ->emailOutputOnFailure('security@company.com');
    
    // Daily quick scan
    $schedule->command('secure:scan --quick')
             ->daily()
             ->at('03:00');
}

๐Ÿ› Troubleshooting

Command not found
# Error: Command "secure:scan" is not defined

# Fix:
composer dump-autoload
php artisan config:clear
php artisan cache:clear

# Verify installation:
composer show bigdevwhale/laravel-secure-baseline
SARIF upload fails in GitHub Actions
# Error: 403 Forbidden when uploading SARIF

# Fix: Add permissions
jobs:
  security:
    permissions:
      security-events: write  # Required!
      contents: read
False positives
// Disable specific checks
'scanners' => [
    'headers' => [
        'checks' => [
            'csp' => false,  // Disable CSP check if using Cloudflare
        ],
    ],
],
Scan too slow
# Use quick mode (3x faster)
php artisan secure:scan --quick

# Or disable slow scanners
# config/secure_baseline.php
'scanners' => [
    'sensitive_data' => [
        'enabled' => false,  // Log scanning is slowest
    ],
],

๐Ÿ“œ License

MIT License. See LICENSE for details.

โญ Show Your Support

If Laravel Secure Baseline helps secure your application:

  1. โญ Star the repo
  2. ๐Ÿ“ Write a blog post 3๐Ÿ’ฌ Share in Laravel communities

Made with โค๏ธ for the Laravel community

GitHub โ€ข Packagist โ€ข Email

Security is not a feature, it's a requirement