NPM dependency hell: comparison with Symfony, Laravel and API Platform

You may have noticed the recent fuss about the compromise of event-stream, a popular NPM package:

event-stream is a transitive dependency of many popular JavaScript projects including Vue, Angular, Gatsby and VSCode (some of them are using a version that isn’t affected by the attack).

This attack raised, again, the problem of the JS dependency cascade: when you install a major project, it comes with hundreds of tiny libraries, sometimes not maintained, and sometimes coming from untrusted sources.

Some claimed that the problem wasn’t specific to the JavaScript ecosystem, and that projects in other languages such as Rails and Symfony were also suffering from a similar dependency hell.
A Twitter poll created by Rafael Dohms highlights that most developers believe that it’s only a matter of luck if this issue has affected the JavaScript ecosystem, and not the PHP one:

Regarding Symfony, as a maintainer I have the feeling that the Symfony Core Team (carefully) adds dependencies only when strictly necessary. However I had no metrics to prove it. So I checked. Then I compared with other PHP frameworks I’m interested in: Laravel and API Platform.


When installing Symfony 4.1 using the official skeleton, only 20 packages are downloaded (19 when excluding dev dependencies). 16 are directly maintained by the Symfony project, and the 4 others are interfaces from the PHP Framework Interoperability Group:

$ composer create-project symfony/skeleton nb-deps

$ composer info | wc -l


$ composer info | cut -d/ -f1 | uniq



Even when installing the website skeleton, that comes with all features provided by the framework and third party (trusted) packages such as the Doctrine ORM, the Twig templating library or Swift Mailer, only 94 packages (75 when excluding dev dependencies), from 17 different organisations (14 without dev deps) are installed:

$ composer create-project symfony/website-skeleton nb-deps

$ composer info | wc -l


$ composer info | cut -d/ -f1 | uniq
















Among these vendors, 7 are directly maintained by members (or former members) of the Symfony Core Team (easycorp, monolog, sensio, swiftmailer, symfony, twig, webmozart) and 2 are from the FIG. All these few libraries, except maybe jdorn/sql-formatter, are actively maintained, by prominent and well known members of the PHP community.

API Platform

A minimal installation of the server part (the one written in PHP) of the API Platform framework contains only 27 packages (26 without dev deps) from 5 vendors.

$ composer create-project symfony/skeleton nb-deps

$ composer require api-platform/core

$ composer info | wc -l


$ composer info | cut -d/ -f1 | uniq






When installing the API pack, that provides all features you can expect from an advanced web API (hypermedia support, automatic persistence with the Doctrine ORM support, automatic generation of human-readable documentation, CORS support, authorisation rules…), 57 packages (56 without dev deps) from 10 vendors are shipped.

$ composer create-project symfony/skeleton nb-deps

$ composer require api

$ composer info | wc -l


$ composer info | cut -d/ -f1 | uniq










On the other hand, the API Platform distribution comes with (optional) frontend tools: an admin and a Progressive Web Apps and mobile apps generator. They are built-on top of React, so even if the JavaScript libraries directly maintained by the API Platform team depend of just a few carefully selected libraries… these dependencies are typical JavaScript ones, and come with hundreds of dependencies (see after).


The default installation of Laravel (that is somewhat similar in term of features to the Symfony website skeleton) comes with 72 packages (39 when excluding dev deps) from 35 vendors (21 when excluding dev deps).

$ laravel new nb-deps

$ composer info | wc -l

$ composer info | cut -d/ -f1 | uniq

The number of maintainers you have to trust when using Laravel is just a bit larger than when using Symfony, but again it’s still a bunch of people that are well known in the PHP community, and who may fit in a single room.

In comparison, a default installation of React using Create React App – that is more similar to the minimal Symfony skeleton than to fully-featured frameworks such as the Symfony website skeleton or Laravel – comes with 809 packages, most of them being maintained by different teams or individuals.

Another main difference is that most JS libraries are distributed as compiled and minified builds. Therefore it’s very difficult to guarantee that what is shipped and executed behaves exactly the same way than the code in the sources. In PHP, the source of the libraries are used directly, without intermediate obfuscation.  PHP builds are easy to reproduce, it helps a lot when auditing.

Of course, it doesn’t mean that major PHP frameworks are immune to this kind of attacks and – as any IT project – they also have their own security issues. However, the amount of third party code installed and the chain of trust you have to rely on is more under control than in the JS world.

By the way, you’d better actively monitor the security vulnerabilities that may affect your PHP projects.

Generate a Symfony password hash from the command line

There is an easy way to generate a Symfony compliant password hash from the command line. Assuming you’re using the bcrypt algorithm (the preferred choice according to Symfony’s security best practices), the default cost (13) and you have PHP >= 5.5 installed, just run the following command:

php -r "echo password_hash('ThePassword', PASSWORD_BCRYPT, ['cost' => 13]) . PHP_EOL;"

 It will output something like: $2y$13$7mBTrD0lgdgBxt1.YbdvOOeSOrPUYOBfeC1Ra2osPs9lpCHdplw1m

You can directly use this value in your app/config/security.yml  file:

            pattern:    ^/
            anonymous: ~
                realm: "Secured Demo Area"

        - { path: ^/admin, roles: ROLE_ADMIN }

                    admin: { password: "$2y$13$7mBTrD0lgdgBxt1.YbdvOOeSOrPUYOBfeC1Ra2osPs9lpCHdplw1m", roles: 'ROLE_ADMIN' }

        Symfony\Component\Security\Core\User\User: bcrypt

Thanks to Sarah Khalil, a built-in Symfony command will be available in a next release (and that command will support all installed algorithms).

DunglasAngularCsrfBundle: protect your Symfony / AngularJS apps against CSRF attacks

I create and I see more and more web applications sharing the same powerful architecture:

 These components share the same philosophy (built on top of dependency injection and MVC-like patterns, designed to be intensively tested) and play very well together.

This stack allows to create awesome blazing-fast web applications. Better, the client part and the server part of the app are loosely coupled, can evolve separately and can even be maintained by different teams.

However, this kind of apps often suffer of security problems, and especially Cross-site Request Forgery (CSRF or XSRF) vulnerabilities.

Both Symfony and AngularJS provide their own CSRF protection mechanisms, but by default they are not interoperable and not enabled. Thanks to a recent refactoring of the Symfony’s security component, it’s now possible and clean to make both systems working together, and I’ve just released an open source bundle to do that: DunglasAngularCsrfBundle.

This bundle provides out of the box CSRF protection for AngularJS apps interacting with a Symfony-backed app.

Despite it’s name, it does not depend of AngularJS and can also be used with Chaplin.js / Backbone.js, jQuery or even raw JavaScript. To do so, install and configure the bundle, then just add to XHR requests a HTTP header called X-XSRF-TOKEN containing the value of the token set by a cookie on the first HTTP request. The bundle will automatically check the validity of the provided token. If it is not valid, an Access Denied error (HTTP 401) will be thrown.

The bundle is fully tested with phpspec and obtain a platinum medal on the brand new (awesome) SensioLabs Insight quality monitoring system.

Internals documentation and installation instructions are provided on the GitHub page of the bundle. Check it, test it, star it and tell me what you think of it!

Download DunglasAngularCsrfBundle on GitHub. 

Patch to use sfXssSafePlugin with symfony 1.2

HTML Purifier is a awesome PHP filter library designed to secure and add standard compliance to HTML. In websites including user generated content, this library allow to have mutlimedia pages including image, text formating and YouTube videos in a secure and SEO proof way thanks to rich text editors like Tiny MCE or FCK Editor and HTML purifier.

A plugin called sfXssSafePlugin is designed to integrate this library as an escapement strategy in symfony. If you have tried it with symfony 1.2 you can see this message:

HTML Purifier autoloader registrar is not compatible
with non-static object methods due to PHP Bug #44144;
Please do not use HTMLPurifier.autoload.php (or any
file that includes this file); instead, place the code:
spl_autoload_register(array(‘HTMLPurifier_Bootstrap’, ‘autoload’))
after your own autoloaders.

There are also some strict standards and constants compatibility problems. I’ve just wrote a patch to get this plugin working with symfony 1.2.

  1. Install sfXssSafePlugin like described in its README file
  2. Download my patch in the plugin’s folder
  3. Go into the plugin’s folder and run patch lib/helper/XssSafeHelper.php < XssSafeHelper.php.patch
  4. Edit your application configuration file (ie: apps/frontend/config/frontendConfiguration.class.php) and add the following code into the configure() method:
    spl_autoload_register(array('HTMLPurifier_Bootstrap', 'autoload'));

It’s done ! I’ve submitted this patch to the plugin’s author. I hope it will be upstream soon 🙂

MessengerFX’s security problem corrected

Some times ago I found a Cross Site Scripting vulnerability in MessengerFX, a popular web-based Windows Live Messenger client. Friday I received from the team saying that the problem is now corrected:

Hi Kevin,
First of all i want to thank you for your warn. We fixed that problem and
now its working correctly.

If you find any other problem please let me know. Thanks again.

It was serious : Every software’s feature is available through Javascript. Any contact of a MessengerFX user can crash his browser, and futhermore get its contact list, add, remove, ban and unban contacts, read and send messages to any other contact of the victim ! Basically, an attacker just need to be listed in the contacts list of an MessengerFX user and this attacker can take control over the account.

In fact, all Javascript code is now removed server-side, so it’s impossible to send some snippets to a friend and the code is still executed locally (in the browser of the sender). The team explain that a new version of their app will be released soon and will better handle things like this.

MessengerFX allows your contacts to take control over your WLM

I have paste some HTML code to a Edouard using MessengerFX, a popular web Windows Live Messenger client based on AJAX, and – surprise, the code has been interpreted. Oh?! A XSS vulnerability ? Yes, and such a big one!

Every software’s feature is available through Javascript. Any contact of a MessengerFX user can crash his browser, and furthermore get its contact list, add, remove, ban and unban contacts, read and send messages to any other contact of the victim ! Basically, an attacker just need to be listed in the contacts list of an MessengerFX user and this attacker can take control over the account.

And the worst is coming… Using Javascript, it seems easy to write a worm that will, i.e. recursively delete every contacts of the MessengerFX users – say using the vulnerability to get the contact list and delete them one by one. The worm can also try to shutdown the WLM network with a DDOS attack by a heavy load of messages at the same timeusing infected MessengerFX users WLM accounts.

MessengerFX is popular and growing, such a flaw can be very dangerous for a lot of people. I have send a mail to the development team and I hope they will correct their application soon… Because the fix is as simple as a htmlspecialchars() call. MessengerFX users, don’t use it anymore and try Meebo or the official Microsoft WLM web based client. Web developers, never trust the user-submitted data and always escape thos inputs!!

Edit october 6 2008 : the problem is now corrected.