Security Practices

What Is Vulnerability Scanning?

The automated process of identifying known security weaknesses in systems, networks, and applications. Vulnerability scanners compare your system against databases of known vulnerabilities (CVEs) and misconfigurations to produce a report of findings.

How It Works

Vulnerability scanners work by comparing what they observe about your application against databases of known vulnerability signatures and configurations.

Dependency scanning (composer audit) — The scanner reads composer.lock, extracts every installed package name and version (both direct and transitive), and queries the PHP Security Advisories API. Matches are returned with the CVE ID, severity score, and the version that contains the fix. The entire process is deterministic and runs in under one second.

Web application scanning (OWASP ZAP) — The scanner first spiders the application to discover all reachable URLs: it follows links, submits forms, and parses JavaScript for endpoint references. In passive mode, it observes responses for information disclosure (stack traces, server headers, verbose errors). In active mode, it systematically attacks every discovered input with hundreds of payloads: SQL injection strings (' OR 1=1--), XSS payloads (<script>alert(1)</script>), path traversal attempts (../../../etc/passwd), command injection strings (;id;). It analyzes responses for evidence that the payload succeeded — database errors, script execution, file content in the response body.

Infrastructure scanning (nmap, external scanners) — Port scanners probe the server's IP address for open TCP ports, identify the service running on each (via banner grabbing), and compare service versions against CVE databases. Open management ports (Redis 6379, MySQL 3306) that should not be internet-facing are flagged as critical findings.

External attack surface scanning (StackShield) — Scans from the public internet, checking response headers for missing security controls, requesting known sensitive paths for accessibility, verifying SSL certificate validity, and testing that authentication is enforced on protected routes. This catches production-specific misconfigurations that staging scanners miss because staging environments are configured differently.

Types of Vulnerability Scanning

Dependency Scanning (SCA)

Software Composition Analysis — checks installed Composer packages against known CVE databases to find vulnerable versions in your dependency tree.

# Run in CI to fail builds with known CVEs
composer audit --no-dev
# Exit code 1 = advisories found, fail the build

Dynamic Application Scanning (DAST)

Runs against a live application, sending attack payloads to every discovered input to detect reflected SQL injection, XSS, and other runtime vulnerabilities.

docker run -t ghcr.io/zaproxy/zaproxy:stable \
  zap-baseline.py -t https://staging.yourapp.com -r report.html

Static Analysis (SAST)

Analyzes source code without running the application — flags dangerous function calls (`system()`, `eval()`), raw query methods, and unescaped output patterns.

# PHPStan with security extension for SAST
composer require --dev phpstan/phpstan
vendor/bin/phpstan analyse app/ --level=8

Infrastructure Scanning

Probes the server's network ports and service banners to identify exposed services, outdated software versions, and unnecessary open ports.

nmap -sV -p 1-65535 --open yourapp.com
# Flags open Redis, MySQL, or admin ports that should be firewalled

In Laravel Applications

Vulnerability scanning for Laravel includes `composer audit` for dependency CVEs, OWASP ZAP for web application vulnerabilities, and external scanners like StackShield for attack surface monitoring. Each covers a different layer of your application.

Code Examples

GitHub Actions: Without vs. With Vulnerability Scanning

Vulnerable

# .github/workflows/deploy.yml — NO security scanning
name: Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    steps:
      - uses: actions/checkout@v4
      - run: composer install --no-dev --optimize-autoloader
      - run: php artisan migrate --force
      - run: ./deploy.sh
      # CVEs in dependencies ship to production undetected

Secure

# .github/workflows/deploy.yml — WITH security scanning gates
name: Deploy
on:
  push:
    branches: [main]
jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: composer install --no-dev
      - run: composer audit           # Fails if CVEs found
  deploy:
    needs: [security]               # Deploy blocked until security passes
    steps:
      - uses: actions/checkout@v4
      - run: composer install --no-dev --optimize-autoloader
      - run: php artisan migrate --force
      - run: ./deploy.sh

Real-World Example

Running `composer audit` and finding that your version of symfony/http-foundation has a known vulnerability is vulnerability scanning at the dependency level.

Why It Matters

Vulnerability scanning gives you a systematic baseline of known security issues across your Laravel application and its dependencies. While it cannot find every vulnerability, it reliably catches the most common and well-documented ones — the issues that no application should ship with.

The most important vulnerability scanner for Laravel developers is composer audit, built into Composer 2.4+. It checks composer.lock against the PHP Security Advisories database and returns a list of known CVEs in your installed packages. This should run on every composer install or composer update in CI/CD. If you are using GitHub, Dependabot can automate PR creation for security updates.

Web application scanners like OWASP ZAP test the running application for OWASP Top 10 vulnerabilities. They spider your routes, submit forms with malicious payloads, and report findings. For effective scanning, point ZAP at a staging environment with realistic seed data and authentication configured.

External attack surface scanners like StackShield complement code and dependency scanners by checking things only visible from the outside: security headers, SSL certificate health, exposed debug tools, DNS configuration, and open ports. Together, these three layers — dependency scanning, web application scanning, and external surface scanning — cover the full vulnerability landscape of a Laravel application.

Common Misconceptions

Myth: Running `composer update` eliminates vulnerability scan findings.

Reality: `composer update` upgrades packages but does not guarantee all security vulnerabilities are resolved — some CVEs affect ranges of versions, and the fix may require a major version bump or configuration change.

Myth: If our CI passes, we have no known vulnerabilities.

Reality: CI typically only runs tests defined by the development team. Unless `composer audit`, OWASP ZAP, or similar tools are explicitly included in the CI pipeline, security scanning does not happen automatically.

Myth: Vulnerability scanning only applies to external-facing applications.

Reality: Internal applications face the same vulnerabilities. Insider threats, compromised developer machines, and pivot attacks from other compromised systems make internal application security equally important.

How to Detect This

Run `composer audit` from your project root to check for dependency CVEs — if it exits with code 1, security advisories exist for your installed packages. Integrate this into your CI/CD with a step that fails the build on audit findings. For web application vulnerabilities, run OWASP ZAP in active scan mode against your staging environment: `docker run -t owasp/zap2docker-stable zap-full-scan.py -t https://staging.yourdomain.com`. StackShield provides continuous external vulnerability scanning without requiring access to your source code or deployment pipeline, catching regressions introduced between CI runs and identifying issues specific to your production environment that staging does not reproduce.

How to Prevent This in Laravel

  1. 1

    Add `composer audit --no-dev` as a required CI step that fails the build on any advisory — place it before deployment steps so vulnerable code never reaches production.

  2. 2

    Configure Dependabot in `.github/dependabot.yml` with `package-ecosystem: composer` to automatically open pull requests when security advisories are found for your Composer packages.

  3. 3

    Run OWASP ZAP baseline scan (`zap-baseline.py`) against your staging environment in CI on every pull request — it catches reflected XSS and injection issues before code is merged.

  4. 4

    Schedule a weekly `composer outdated --direct` review to proactively update packages that haven't received CVEs yet but are significantly behind their latest release.

  5. 5

    Add StackShield or an equivalent external scanner to your deployment pipeline to catch production-environment misconfigurations that staging scans miss (different env variables, different web server config).

Frequently Asked Questions

Is `composer audit` alone enough vulnerability scanning for a Laravel application?

`composer audit` covers dependency CVEs only — a critical layer, but one of four. You also need web application scanning (OWASP ZAP for runtime injection and XSS vulnerabilities), static analysis (PHPStan with security rules for code-level issues), and external attack surface scanning (StackShield for configuration vulnerabilities and infrastructure issues). Each layer catches a different class of vulnerability that the others miss.

How do I integrate OWASP ZAP into my Laravel CI/CD pipeline?

Use the OWASP ZAP Docker image in your GitHub Actions workflow: `docker run -t ghcr.io/zaproxy/zaproxy:stable zap-baseline.py -t https://staging.yourapp.com`. The baseline scan runs passively and returns exit code 2 for alerts and 1 for errors. Configure your staging environment to be accessible from GitHub Actions runners, or use ZAP's `zap-api-scan.py` for API-specific scanning with an OpenAPI spec file.

Will vulnerability scanning find all security issues in my application?

No — automated scanners miss logic vulnerabilities, IDOR issues that require understanding business context, and multi-step attack chains that require stateful interaction. `composer audit` misses zero-days (not yet in the CVE database). OWASP ZAP misses stored XSS in content areas it cannot authenticate to. External scanners miss internal code issues. Automated scanning is a necessary baseline, not a complete security program — it should be complemented by code review and periodic penetration testing.

How do I reduce false positives from OWASP ZAP scans?

Configure ZAP with authentication so it scans authenticated routes rather than triggering constant login failures. Use ZAP's context configuration to set the application URL scope and exclude known non-vulnerable paths (like `/api/health`). Review the ZAP alert taxonomy and suppress known false positives using ZAP's `.zap` configuration file. Running in passive scan mode first before enabling active scan gives you a baseline of which alerts are real in your specific application context.

Related Terms

Related Articles

Monitor Your Laravel Application's Security

StackShield continuously checks your Laravel application from the outside, catching security issues before attackers find them.

Start Free Trial