Search by

salvatorecervone / laravel-pentest

SalvatoreCervone

Automated In-App Penetration Testing and DAST Security Audit Suite for Laravel

Package info

github.com/SalvatoreCervone/laravel-pentest

pkg:composer/salvatorecervone/laravel-pentest

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-09-13 20:46 UTC

This package is auto-updated.

Last update: 2026-09-13 20:50:10 UTC


README

Latest Version on Packagist Total Downloads Laravel Support PHP Support License Build Status

Automated In-App Penetration Testing and DAST Security Audit Suite for Laravel.

laravel-pentest turns your Laravel CLI and test environment into an automated, in-app offensive security tester. It scans and simulates real-world attack vectors against your routes, Eloquent models, controllers, database connections, and configurations to detect critical security gaps before bad actors do:

  • BOLA / IDOR vulnerabilities (missing Policy & Gate authorizations on resource models)
  • Mass Assignment flaws ($guarded = [], risky $fillable columns, unfiltered $request->all())
  • Unprotected Admin Routes (sensitive endpoints missing authentication middleware)
  • Missing Rate Limiters (brute-force exposure on login, 2FA, and password-reset endpoints)
  • Insecure HTTP Security Headers (missing CSP, HSTS, X-Frame-Options, X-Content-Type-Options)
  • Active Debug & Secret Leaks (APP_DEBUG=true in production, exposed .env and .git files)
  • Database Hardening & Least Privilege (weak/empty passwords, root/superuser connection, missing TLS/SSL on remote DBs, exposed SQLite)
  • Sensitive Data & PII Exposure (unencrypted PII columns without casts = ['...' => 'encrypted'], secrets leaked outside $hidden)
  • Cryptographic & Key Integrity (missing/weak APP_KEY, low bcrypt work factors, insecure .env filesystem permissions)
  • SQL Injection in Raw Queries (string concatenations in whereRaw(), havingRaw(), orderByRaw(), and DB::raw())
  • Session & Cookie Hardening (missing secure, disabled http_only, insecure same_site flags)
  • CORS Misconfiguration (wildcard origins with credentials, permissive regexes, sensitive exposed headers)

Table of Contents

Requirements

  • PHP: ^8.2
  • Laravel Framework: ^10.0, ^11.0, or ^12.0

Installation

Install the package via Composer as a development dependency:

composer require --dev salvatorecervone/laravel-pentest

Publish the package configuration file (optional):

php artisan vendor:publish --tag="pentest-config"

Usage

Run All Penetration Tests

php artisan pentest:run

Output preview:

Initiating Laravel In-App Penetration Testing Suite (6 audits loaded)...
  → Running audit: route-exposure... [PASS]
  → Running audit: idor-bola... [FAIL: 1 findings]
  → Running audit: mass-assignment... [PASS]
  → Running audit: rate-limit... [PASS]
  → Running audit: security-headers... [PASS]
  → Running audit: debug-exposure... [PASS]

+------------------+--------+----------+------+--------+-----+----------+
| Audit Suite      | Status | Critical | High | Medium | Low | Duration |
+------------------+--------+----------+------+--------+-----+----------+
| route-exposure   | PASS   | 0        | 0    | 0      | 0   | 1.45 ms  |
| idor-bola        | FAIL   | 0        | 1    | 0      | 0   | 2.10 ms  |
| mass-assignment  | PASS   | 0        | 0    | 0      | 0   | 3.20 ms  |
| rate-limit       | PASS   | 0        | 0    | 0      | 0   | 0.85 ms  |
| security-headers | PASS   | 0        | 0    | 0      | 0   | 1.10 ms  |
| debug-exposure   | PASS   | 0        | 0    | 0      | 0   | 0.40 ms  |
+------------------+--------+----------+------+--------+-----+----------+

=== DETECTED VULNERABILITIES & REMEDIATION ===

 [HIGH] [CWE-639] Missing authorization policy on [GET] /api/documents/{document} (/api/documents/{document})
   The endpoint binds to a data model 'App\Models\Document' but does not enforce Policy or Gate authorization.
   Remediation: Enforce a policy check: add '->middleware("can:view,document")' or call '$this->authorize("view", $document)'.

Run a Specific Audit Suite

Filter which audit suite to execute using the --suite option:

# Available options: route-exposure, idor-bola, mass-assignment, rate-limit, security-headers, debug-exposure, database-security, sensitive-data, crypto-security, csrf-protection, dependency-security
php artisan pentest:run --suite=csrf-protection

Baseline & False-Positive Suppression

When introducing laravel-pentest to an existing codebase with legacy debt, avoid breaking the CI build by generating a baseline file:

# Snapshot all current findings into .pentest-baseline.json
php artisan pentest:run --generate-baseline

Subsequent runs will automatically suppress known baseline issues, ensuring only new security regressions trigger alerts and fail the CI pipeline:

php artisan pentest:run --fail-on-vuln

Fail CI Pipeline on Vulnerabilities

Exit with status code 1 if any Critical or High vulnerability is identified:

php artisan pentest:run --fail-on-vuln

Or exit with status code 1 on any finding (including low or medium):

php artisan pentest:run --strict

Generate Standalone HTML Report

Export a beautifully formatted, responsive standalone HTML security report:

php artisan pentest:run --report=storage/reports/security-audit.html

Interactive Web Security Dashboard

Launch live security scans directly in your browser with real-time feedback and an interactive vulnerability explorer:

  • Access URL: http://localhost:8000/pentest (or your configured application domain)
  • Enabled by default in local and testing environments (configurable in config/pentest.php).
  • Zero external dependencies (pure vanilla CSS & lightweight JS).
  • Allows developers to trigger full audits with a single click and review findings with remediation advice instantly.

Security Baseline & False Positive Suppressions

Prevent legacy findings from blocking ongoing CI workflows while ensuring zero new regressions:

# Snapshot existing vulnerabilities into a baseline file
php artisan pentest:run --generate-baseline=pentest-baseline.json

# Run subsequent scans ignoring existing baseline findings
php artisan pentest:run --baseline=pentest-baseline.json --fail-on-vuln

You can also suppress specific false positives permanently in config/pentest.php:

'suppressions' => [
    'UNPROTECTED_SENSITIVE_ROUTE:/api/public-report',
],

Safe Database Probing (DatabaseSandbox)

When performing active security probes or simulating input mutation against models and database connections, laravel-pentest provides transactional rollback isolation:

use LaravelPentest\Support\DatabaseSandbox;

DatabaseSandbox::executeInTransaction(function () {
    // Probing or test mutation runs here
    // Automatically rolled back in a finally block — zero persistence!
});

Audit Suites & Vulnerabilities Detected

Suite Vulnerability ID CWE Default Severity What It Tests
route-exposure UNPROTECTED_SENSITIVE_ROUTE CWE-306 CRITICAL / HIGH Scans registered routes for sensitive paths (admin/*, users/*, billing/*, reports/*) that lack authentication middleware.
idor-bola POTENTIAL_IDOR_BOLA CWE-639 HIGH Analyzes Route-Model binding endpoints to verify that Policies, Gates, or FormRequests protect user resources against horizontal privilege escalation.
mass-assignment UNGUARDED_ELOQUENT_MODEL CWE-915 CRITICAL Detects models declaring $guarded = [] without $fillable, leaving database columns open to arbitrary modifications.
mass-assignment DANGEROUS_FILLABLE_ATTRIBUTES CWE-915 HIGH Identifies privileged fields (is_admin, role_id, balance, permissions, is_superadmin) dangerously declared inside $fillable.
mass-assignment UNFILTERED_REQUEST_MASS_ASSIGNMENT CWE-915 HIGH Flags controller methods passing unfiltered $request->all() directly into Model::create() or $model->update().
csrf-protection MISSING_CSRF_PROTECTION CWE-352 HIGH Verifies state-changing routes (POST, PUT, PATCH, DELETE) enforce CSRF token validation.
rate-limit MISSING_RATE_LIMITING CWE-307 HIGH Ensures that authentication, login, password recovery, and token endpoints enforce throttling (throttle:x,y) against brute force.
security-headers MISSING_X_FRAME_OPTIONS CWE-1021 MEDIUM Checks HTTP responses for clickjacking defenses (X-Frame-Options: SAMEORIGIN / DENY).
security-headers MISSING_CSP CWE-79 MEDIUM Checks for missing Content-Security-Policy (CSP) header.
security-headers MISSING_HSTS CWE-319 MEDIUM Asserts that Strict-Transport-Security (HSTS) is enabled in production.
security-headers MISSING_X_CONTENT_TYPE_OPTIONS CWE-79 LOW Verifies the X-Content-Type-Options: nosniff header to block MIME sniffing.
debug-exposure APP_DEBUG_ENABLED_IN_PRODUCTION CWE-489 CRITICAL Detects APP_DEBUG=true in production environments, exposing stack traces and database credentials.
debug-exposure EXPOSED_SENSITIVE_FILE CWE-552 CRITICAL / HIGH Checks whether sensitive files (.env, .git, storage/logs/laravel.log, .sql dumps) are placed in the public/ web root.
database-security EMPTY_DATABASE_PASSWORD CWE-521 CRITICAL Flags blank/missing passwords on network database connections.
database-security WEAK_DATABASE_PASSWORD CWE-521 CRITICAL Detects trivial/default passwords (root, admin, 123456, secret).
database-security HIGHLY_PRIVILEGED_DATABASE_USER CWE-250 HIGH Detects connecting as DBA/superuser (root, postgres, sa), violating Least Privilege.
database-security UNENCRYPTED_REMOTE_DATABASE_CONNECTION CWE-319 HIGH Verifies remote databases enforce TLS/SSL (sslmode=require / MYSQL_ATTR_SSL_CA).
database-security EXPOSED_SQLITE_DATABASE CWE-552 CRITICAL Flags SQLite databases stored inside the public/ web directory.
sensitive-data UNENCRYPTED_SENSITIVE_ATTRIBUTE CWE-311 HIGH Identifies PII columns (ssn, tax_number, credit_card, iban) missing casts = ['...' => 'encrypted'].
sensitive-data SENSITIVE_ATTRIBUTE_NOT_HIDDEN CWE-200 HIGH Detects secrets and auth tokens (password, two_factor_secret, api_token) missing from Eloquent $hidden.
crypto-security MISSING_APP_KEY / PLACEHOLDER_APP_KEY CWE-321 CRITICAL Asserts APP_KEY exists, is non-default, and matches cipher bit requirements.
crypto-security WEAK_BCRYPT_ROUNDS CWE-916 HIGH Validates password hashing work factors (bcrypt.rounds >= 10, recommended 12+).
dependency-security VULNERABLE_COMPOSER_DEPENDENCY CWE-1395 CRITICAL / HIGH Scans composer.lock for known advisories and CVEs in dependencies.
dependency-security ABANDONED_OR_DEPRECATED_PACKAGE CWE-1104 MEDIUM Warns about abandoned packages with known migration alternatives.
cors-security CORS_WILDCARD_WITH_CREDENTIALS CWE-942 CRITICAL Detects wildcard allowed origins (*) combined with supports_credentials => true.
cors-security CORS_PERMISSIVE_ORIGIN_REGEX CWE-942 HIGH Flags unanchored or overly permissive regular expressions in allowed_origins_patterns.
cors-security CORS_SENSITIVE_EXPOSED_HEADER CWE-200 MEDIUM Identifies authorization and session headers exposed to cross-origin callers.
session-security SESSION_COOKIE_NOT_SECURE CWE-614 HIGH Ensures session cookies enforce the secure flag in production/staging environments.
session-security SESSION_COOKIE_NOT_HTTPONLY CWE-1004 CRITICAL Asserts http_only => true to prevent session hijacking via JavaScript document.cookie.
session-security SESSION_COOKIE_SAMESITE_INSECURE CWE-1275 HIGH Validates same_site => 'lax' or 'strict' to prevent cross-site request leakage.
session-security EXCESSIVE_SESSION_LIFETIME CWE-613 LOW Warns if session expiration exceeds 30 days without re-authentication.
sqli-safety SQL_INJECTION_RAW_QUERY CWE-89 CRITICAL Scans controller methods for unparameterized string concatenations in whereRaw, havingRaw, orderByRaw, and DB::raw.

Writing Tests with InteractsWithPentest

Integrate pentest assertions directly into your existing PHPUnit or Pest test suites:

namespace Tests\Feature;

use App\Models\Customer;
use App\Models\User;
use LaravelPentest\Testing\InteractsWithPentest;
use Tests\TestCase;

class SecurityRegressionTest extends TestCase
{
    use InteractsWithPentest;

    public function test_sensitive_routes_are_protected_from_guests(): void
    {
        $this->assertRouteProtectedFromGuest('/admin/dashboard');
        $this->assertRouteProtectedFromGuest('/billing/invoices');
    }

    public function test_auth_routes_have_rate_limiting(): void
    {
        $this->assertRouteHasRateLimiting('/login');
        $this->assertRouteHasRateLimiting('/password/reset');
    }

    public function test_models_have_encryption_and_hidden_attributes(): void
    {
        $this->assertModelIsGuarded(User::class);
        $this->assertModelHidesAttributes(User::class, ['password', 'two_factor_secret']);
        $this->assertModelEncryptsAttributes(Customer::class, ['ssn', 'credit_card']);
    }

    public function test_no_critical_pentest_vulnerabilities_exist(): void
    {
        $this->assertNoPentestVulnerabilities();
    }
}

CI/CD Integration (GitHub Actions)

Add this workflow to your repository (.github/workflows/security-pentest.yml) to automatically block pull requests containing new security regressions:

name: Security Pentest Audit

on:
  push:
    branches: [ "main", "develop" ]
  pull_request:
    branches: [ "main" ]

jobs:
  security-audit:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          extensions: mbstring, pdo_sqlite, curl

      - name: Install Dependencies
        run: composer install --prefer-dist --no-progress

      - name: Run In-App Penetration Tests
        run: php artisan pentest:run --fail-on-vuln --report=security-report.html

      - name: Upload Security Report Artifact
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: security-audit-report
          path: security-report.html

Configuration

You can customize the scan behavior in config/pentest.php:

return [
    // Patterns of routes to skip (e.g. dev debuggers, health routes)
    'ignore_routes' => [
        '_ignition/*',
        '_debugbar/*',
        'telescope/*',
        'horizon/*',
        'pulse/*',
        'up',
        'sanctum/csrf-cookie',
    ],

    // Additional directories where Eloquent models should be discovered
    'models_paths' => [
        // app_path('Domain/Billing/Models'),
    ],

    // Minimum severity to fail CI command ('CRITICAL', 'HIGH', 'MEDIUM', 'LOW')
    'fail_on_severity' => env('PENTEST_FAIL_SEVERITY', 'HIGH'),

    // Database Hardening & Security Audit
    'database' => [
        // Connections to audit. Null defaults to config('database.default')
        'connections' => env('PENTEST_DB_CONNECTIONS', null),

        // Fallback/override credentials when not stored in .env
        // Useful for CI runners, Docker secrets, or AWS Secrets Manager
        'credentials' => [
            'mysql' => [
                'username' => env('PENTEST_DB_USERNAME'),
                'password' => env('PENTEST_DB_PASSWORD'),
            ],
        ],

        // Allow blank passwords if database uses socket or IAM authentication
        'allow_empty_password' => env('PENTEST_DB_ALLOW_EMPTY_PASSWORD', false),

        // Custom weak password dictionary
        'weak_passwords' => [
            '', 'root', 'admin', 'password', '123456', 'secret',
        ],
    ],

    // Sensitive Data & PII Audit
    'sensitive_data' => [
        // Columns that should have 'encrypted' casts in Eloquent
        'sensitive_attributes' => [
            'ssn', 'tax_number', 'fiscal_code', 'credit_card', 'iban', 'bank_account', 'passport',
        ],

        // Attributes that must be hidden from API JSON responses
        'critical_hidden_attributes' => [
            'password', 'remember_token', 'two_factor_secret', 'api_token',
        ],
    ],

    // Cryptographic & Environment Audit
    'crypto' => [
        // Minimum bcrypt rounds (OWASP recommends >= 10, default 10)
        'min_bcrypt_rounds' => 10,

        // Check if .env has world-readable filesystem permissions
        'check_env_permissions' => true,
    ],
];

Running Tests

Run the test suite with PHPUnit:

composer test

Security Vulnerabilities

If you discover a security vulnerability within laravel-pentest, please open an issue or submit a pull request on GitHub.

License

The MIT License (MIT). Please see License File for more information.