
September 10, 2026
12 min read
By Kokil Thapa | Last reviewed: September 2026
Your application code may be clean, yet a single outdated package can still expose customer data. Dependency Scanning (Software Composition Analysis) maps every third-party library in your stack to published CVE records before deploy. On production Laravel and PHP projects I maintain, SCA catches issues that code review and unit tests never touch. This guide covers lockfile scanning, CI wiring, triage, and fixes you can run today.
What is Dependency Scanning (Software Composition Analysis)?
SCA answers one question: do the libraries you import contain known security flaws? Modern apps rarely ship without dependencies. A typical custom Laravel application pulls in hundreds of transitive packages through Composer alone. You did not write that code, but you own the risk when it lands in production.
Software Composition Analysis tools read your dependency manifests and lockfiles. They match package names and exact versions against advisory feeds such as the GitHub Advisory Database and the National Vulnerability Database (NVD). The output is a report ranked by severity—critical, high, medium, low—with CVE identifiers and recommended fixed versions.
This is not the same as scanning your own source for bugs. SCA looks outward at supply-chain risk. On a legal-tech portal or eCommerce site, one vulnerable JWT library or file-upload helper can compromise the entire platform. I treat SCA as non-negotiable for any client project that handles payments, documents, or personal data.
Core inputs SCA tools require
Every scanner needs deterministic version pins. Without a lockfile, two developers can install different patch levels and get different scan results. For PHP projects, commit composer.lock. For front-end assets built with Vite 8.x and npm 12, commit package-lock.json or pnpm-lock.yaml.
- composer.lock — PHP and Laravel 12/13 dependencies installed via Composer 2.10
- package-lock.json — Node.js build tooling and JavaScript libraries
- Container images — OS packages layered on top of application deps; pair with container image scanning
- SBOM files — machine-readable inventories from tools covered in our SBOM generation guide
How do you set up dependency scanning in a Laravel or PHP project?
Start with the native tools before adding SaaS platforms. Composer ships composer audit since Composer 2.4. On PHP 8.3+ Laravel 13 projects, this is the fastest baseline. Run it locally, then enforce it in CI.
Composer audit for PHP dependencies
# Install deps exactly as production will
composer install --no-dev --prefer-dist --no-interaction
# Fail the command when advisories exist
composer audit --format=json
# Human-readable summary
composer audit
The JSON output integrates cleanly with GitLab CI artifacts or custom parsers. Store it beside your JSON formatter output during local debugging so you can read CVE blocks without squinting at terminal walls.
For development dependencies, run a separate audit pass with dev packages included. A vulnerable PHPUnit or Debugbar version rarely affects production, but it can compromise developer machines and CI runners.
npm audit for Vite and front-end packages
Laravel apps using Vite 8.x typically maintain a package.json at the project root. After npm ci, run:
npm ci
npm audit --audit-level=high
npm audit fix --dry-run
Never blindly run npm audit fix --force on a production branch. Major semver jumps break builds. Review each advisory, check whether the vulnerable code path is reachable, then bump intentionally.
OWASP Dependency-Check for polyglot repos
When a project mixes PHP, JavaScript, and WordPress 7.1 plugins, a unified scanner helps. OWASP Dependency-Check supports Composer, npm, and several other ecosystems in one CLI pass. It is heavier than native audits but produces HTML and JSON reports suitable for compliance folders.
- Install the CLI or use the official Docker image in CI.
- Point it at the project root with
--scan. - Configure suppression XML for false positives you have verified.
- Archive reports per release tag for audit trails.
On sister sites I deploy with Deployer 7 and GitLab CI, I run Composer audit on every pipeline. OWASP Dependency-Check runs nightly because it takes longer. That split keeps pull request feedback fast without losing depth.
How does dependency scanning differ from static code analysis and secrets scanning?
Teams often conflate three security layers. Each covers a different attack surface. Running only one leaves obvious gaps.
| Scan type | What it inspects | Typical tools | Finds |
|---|---|---|---|
| Dependency Scanning (SCA) | Third-party packages via lockfiles | composer audit, npm audit, Snyk, Dependabot | Known CVEs in libraries you did not write |
| Static code analysis (SAST) | Your source code patterns | PHPStan, SonarQube, Psalm | SQL injection risk, type errors, dead paths |
| Secrets scanning | Git history and working tree | gitleaks, GitHub secret scanning | Committed API keys, tokens, passwords |
Pair SCA with PHPStan static analysis and secrets scanning in Git. On a client portal like Mijar Law Associates, document uploads and payment callbacks need clean application code and clean dependencies. One layer alone is not enough.
SonarQube in CI excels at code smells and coverage. It does not replace checking whether symfony/http-kernel at a pinned version has an open advisory. Keep both jobs in the pipeline with separate failure thresholds.
How do you integrate SCA into GitLab CI or GitHub Actions?
Scanning locally is useful. Blocking vulnerable merges is what changes behaviour. Wire dependency scans into the same pipeline that runs tests and linting. Fail fast on critical CVEs; warn on medium findings until the backlog clears.
GitLab CI example for Laravel
stages:
- test
- security
composer_audit:
stage: security
image: php:8.3-cli
script:
- curl -sS https://getcomposer.org/installer | php -- --2
- php composer.phar install --no-dev --prefer-dist --no-interaction
- php composer.phar audit --format=plain
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
npm_audit:
stage: security
image: node:26-bookworm
script:
- npm ci
- npm audit --audit-level=high
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
Cache vendor/ and node_modules/ between jobs to keep pipeline times sane. On shared EC2 runners I manage, a cold Composer install adds two to four minutes. Caching cuts that sharply.
For deeper coverage, add a scheduled job using Snyk developer-first scanning or OWASP Dependency-Check. Scheduled scans catch new CVEs published after your last merge.
GitHub Dependabot and advisory alerts
GitHub repositories can enable Dependabot security updates and version bumps via .github/dependabot.yml. Dependabot opens pull requests when advisories affect your lockfiles. Review each PR like any other dependency upgrade—run tests, check changelogs, confirm Laravel compatibility.
version: 2
updates:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
Dependabot is not a substitute for CI gates. It proposes fixes. Your pipeline still must prove the upgrade passes. See our dependency vulnerability scanning setup article for a full baseline configuration.
What should you do when a scan finds a critical CVE?
A red pipeline is only useful if the team has a triage playbook. Panic-merging a major version bump breaks more than it fixes. Work through severity, reachability, and available patches in that order.
Triage steps that work in production
- Confirm reachability. Does your app call the vulnerable function or code path? A flaw in an unused CLI subcommand may not affect your web routes.
- Check upstream fixes. Run
composer update vendor/package --with-dependencieson a branch. Read the changelog for breaking changes. - Run your test suite. Include integration tests for affected modules—auth, file upload, payment callbacks.
- Document waivers. If no fix exists yet, record the CVE, business risk, compensating controls, and review date in a
security/exceptions.mdfile. - Deploy and verify. After merge, confirm production lockfiles match CI. Stale
vendor/on a server is a classic post-deploy gap.
For WooCommerce 11.1 or WordPress plugin stacks, vendor updates sometimes lag weeks behind core advisories. In those cases, disable affected features temporarily, add WAF rules, or restrict admin access until the plugin author ships a patch.
On a Laravel eCommerce project like Quick And Easy Nepalese Grocery, payment gateway packages and cart libraries sit on the critical path. I bump those first and run checkout smoke tests before anything else merges.
Common mistakes I see on client codebases
- Scanning
composer.jsonranges instead of the committed lockfile—results drift between machines. - Ignoring devDependency CVEs on CI runners that execute untrusted test code.
- Treating
npm audit fixoutput as gospel without reading semver impact. - Skipping scans on long-lived maintenance branches that still receive hotfixes.
- Deploying built assets without re-scanning after
npm cion the release runner.
Pair dependency work with broader hardening. Rate limiting and abuse prevention reduce exploit impact even when a patch is pending. Our guide on API rate limiting and abuse prevention covers practical middleware patterns for Laravel.
How do you choose between SCA tools for a small team?
Budget and workflow matter as much as feature lists. A five-person agency in Kathmandu does not need the same stack as a regulated fintech. Start free, enforce in CI, then add paid reachability analysis if noise becomes unbearable.
| Tool | Best for | Cost profile | Trade-off |
|---|---|---|---|
| composer audit + npm audit | Laravel/PHP shops, fast CI | Free, built-in | No reachability analysis; you triage manually |
| GitHub Dependabot | GitHub-hosted repos | Free tier available | PR volume can overwhelm small teams |
| OWASP Dependency-Check | Polyglot, compliance reports | Free, self-hosted | Slower scans; false positives need tuning |
| Snyk / similar SaaS | Reachability, dashboards, policies | Paid per developer | Cost scales with headcount (~USD 25–50/dev/month) |
For ongoing maintenance contracts, bundle SCA into your release checklist. Clients on support and maintenance plans expect you to catch CVEs before attackers do. Monthly scan reports take thirty minutes and prevent expensive emergency patches.
Server hardening complements dependency hygiene. An unpatched libssl on Ubuntu undermines even a clean Composer lockfile. Include OS-level updates in your Linux system administration routine and scan container images separately.
AI-assisted review tools can summarise long advisory threads, but they do not replace lockfile scans. Treat AI code review in CI as a helper for human triage, not a substitute for testing and optimization gates you already trust.
Key Takeaways
- Commit lockfiles and run
composer auditplusnpm auditon every pull request—SCA without deterministic pins is unreliable. - Treat Dependency Scanning (Software Composition Analysis) as a separate layer from SAST and secrets scanning; you need all three.
- Block merges on critical CVEs with a written triage path: patch, mitigate, or time-boxed waiver.
- Schedule nightly or weekly rescans because new advisories appear after your last green build.
- Export SBOMs per release so compliance and incident response teams know exactly what shipped.
- Pair dependency updates with integration tests on payment, auth, and upload flows before deploy.
People Also Ask
Is Software Composition Analysis the same as dependency scanning?
Yes. SCA and dependency scanning refer to the same practice: identifying known vulnerabilities in third-party libraries by comparing locked versions against CVE databases. "Composition" emphasises that modern apps are assembled from many external parts, not written entirely in-house.
Does Laravel include built-in dependency scanning?
Laravel itself does not ship an SCA engine. You rely on Composer 2.10's composer audit, CI integrations, GitHub Dependabot, or third-party scanners. Laravel 12 and 13 projects benefit from the same workflow—what changes is PHP version requirements and package compatibility during upgrades.
How often should you run dependency scans?
Run scans on every pull request and on the default branch after merge. Add a nightly scheduled job to catch CVEs published overnight. Before major releases—Dashain-season eCommerce peaks in Nepal, for example—run a manual audit and archive the report.
Can dependency scanning slow down CI pipelines?
Native composer audit and npm audit calls usually add under sixty seconds with cached dependencies. Heavier tools like OWASP Dependency-Check belong in nightly jobs. Split fast gates from deep scans so developers get feedback within minutes, not half an hour.
Ship safer releases with dependency scanning in your pipeline
Dependency Scanning (Software Composition Analysis) turns supply-chain risk into a checklist item you can enforce before deploy. Lock your manifests, wire audits into CI, triage findings with reachability in mind, and keep SBOMs for every release. That workflow has saved me from shipping known CVEs on production Laravel apps more than once.
If you want SCA wired into an existing pipeline—or a full security review of a legacy PHP codebase—contact us for a practical plan. You can also read more on the blog or learn about my background on about me.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

