Current situation: PHP2Shell. Two critical PHP vulnerabilities (CVSS 9.2) allow malicious code without login. Patches since 21 October 2026.What to do now →

Composer: The Package Manager for PHP

Composer downloads and manages the libraries on which modern PHP projects are built. Anyone who understands composer.json, composer.lock and the autoloader deploys reproducibly and more securely.

Last updated 5 min readPHP knowledge

In short: Composer is the package manager for PHP. From the file composer.json it reads which libraries a project needs, downloads them into the vendor folder, records the exact versions in composer.lock and generates an autoloader that finds classes automatically. Composer thus manages your application's code, not the PHP interpreter itself: a Composer update does not close a flaw in PHP such as PHP2Shell.

What is Composer and what is it needed for?

Hardly any PHP application today consists of its own code alone. Frameworks, mail libraries, PDF generation or payment integrations are added as ready-made packages. Composer, the package manager for PHP, ensures that these packages come together in matching versions and that every dependency brings along its own dependencies.

For decision-makers this means: a large part of the code running on your server comes from third parties. That is efficient but needs maintenance. For admins and developers it means: anyone who uses Composer cleanly can trace at any time which version of which library is running in production.

According to the Composer documentation, the default source for packages is Packagist.org. Other sources, such as an agency's internal repositories, can be entered in composer.json under repositories.

composer.json, composer.lock and vendor: the three building blocks

Composer works with three things that you should know before taking over a server or commissioning an agency.

Building block Content Belongs in the repository?
composer.json desired packages with version ranges (require, require-dev), autoload rules, settings yes
composer.lock exactly resolved versions of all packages, including indirect ones yes, explicitly according to the Composer docs
vendor/ downloaded code of the packages and the generated autoloader no, it is generated during installation

Under require are packages the application needs in operation. Under require-dev are tools for development and testing, such as test frameworks or static analysis. This separation is important because development tools have no place on a production server.

{
    "require": {
        "php": ">=8.3",
        "monolog/monolog": "^3.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^11.0"
    },
    "autoload": {
        "psr-4": { "App\\": "src/" }
    }
}

The version numbers in the example are chosen for illustration only. Which versions your project needs follows from its requirements.

install or update: the difference in operation

The two commands sound similar but have very different consequences.

  • composer install reads composer.lock and installs exactly the versions recorded there. This is reproducible and belongs in deployment.
  • composer update resolves all dependencies anew, fetches the latest matching versions and rewrites composer.lock. This belongs in development, followed by tests.

According to the Composer documentation, after writing the lock file update additionally runs a security check (audit), unless it is switched off with --no-audit. install does not check by default; the option --audit exists for that.

Autoloading: how Composer finds classes

Composer generates the file vendor/autoload.php. Once it is included, PHP loads each class only when it is needed. For your own code, the autoload section defines which namespace lives in which folder. PSR-4, a PHP-FIG standard, is recommended for this. Exactly how this works is explained on the page Namespaces and autoloading; an overview of all standards is given on the page PSR standards.

<?php
require __DIR__ . '/../vendor/autoload.php';

$log = new Monolog\Logger('app');   // loaded automatically when needed

Composer in production: deploying cleanly

A fixed sequence has proven itself for deployment. It runs best in a build pipeline and not by hand on the server.

  1. Check the lock file: composer validate ensures that composer.json is valid and composer.lock is up to date.
  2. Install without development packages: composer install --no-dev leaves out require-dev.
  3. Optimise the autoloader: --optimize-autoloader (short -o) converts the rules into a class list. With --classmap-authoritative, PHP loads classes exclusively from this list.
  4. Security check: composer audit --locked checks the versions from the lock file against known security advisories and reports abandoned packages.
  5. vendor outside the web root: Only the public folder with the entry script should be reachable via URL.
composer validate
composer install --no-dev --optimize-autoloader
composer audit --locked --no-dev

composer outdated additionally shows which installed packages have newer versions. This is the basis for planned updates instead of hectic one-off actions.

Composer, security and PHP2Shell

Composer and PHP2Shell concern two different levels. The flaws CVE-2026-109618 and CVE-2026-109619 lie in the PHP interpreter itself. They are fixed in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and all PHP processes must be restarted afterwards. No composer update and no package in vendor changes that.

Even so, Composer belongs in every check after an incident. Anyone who brings malicious code onto a server can also change files in vendor, and vendor/autoload.php is loaded on every request. A fresh composer install from the verified lock file into an empty directory is therefore a good way to restore the package inventory. How to check dependencies regularly for known flaws is described in the guide composer audit.

Important

A green composer audit says nothing about PHP's patch level. Check the PHP runtime separately, for example with our PHP patch service.

How does PHP SOS help?

  • For each application we record the PHP version, Composer packages and lock state, cleanly separating the interpreter from the libraries.
  • We check whether vendor and the lock file match each other and whether development packages or altered files are present in production.
  • We set up reproducible deployment with install --no-dev, an optimised autoloader and audit.
  • After an incident we rebuild the package inventory from the verified lock file and document the result.

Frequently asked questions

Does composer.lock have to go into the Git repository?

Yes. The Composer documentation explicitly recommends committing composer.lock. Only then do development, CI and production install exactly the same package versions.

What is the difference between composer install and composer update?

install installs the versions recorded in composer.lock. update resolves the dependencies anew, fetches suitable newer versions and rewrites composer.lock. On the production server only install belongs.

Does a Composer update close the PHP2Shell flaw?

No. Composer manages your application's libraries, not the PHP interpreter. PHP2Shell is closed only by updating the PHP runtime to a fixed version and restarting all PHP processes.

Where should the vendor folder be located?

Ideally outside the publicly accessible web directory. Many frameworks place only a public folder in the web root, while vendor sits one level above.

Sources

Immediate contact

Every hour counts. Write to us now.

Briefly describe your system, PHP version and observation. We will get back to you, clarify the situation and work remotely until the incident is closed and documented.

Immediate help