Description
Preconditions
- Run Magento 2 (any version) under php-fpm. Any valid php version - tested with php 5.6 to 7.0.11
Steps to reproduce
- Hit it with heavy traffic including xmlrpc calls
- Visit a page on frontend or backend
Expected result
Actual result
- Page displays without head tag (sometimes - intermittent)
This is fixed by clearing the layout cache. This displays in the same way as an issue in Magento 1 - see https://www.c3media.co.uk/blog/c3-news/security-fix-might-take-site
The fix in Magento 1 was to add the following to bootstrap.php:
if (function_exists('libxml_disable_entity_loader')) {
libxml_disable_entity_loader(false);
}
Why is this needed? Because there are a number of places in Magento 2 where $oldval = libxml_disable_entity_loader(true)
is called and then later libxml_disable_entity_loader($oldval)
. In theory this should be fine, but the value is not thread-safe, so when running under php-fpm it only requires a call to occur in between these statements for the entire thread to end up set to TRUE. Why this then corrupts to cache it was never clear in Magento 1, but that was the upshot.
The above fix was added in Magento 1.9.2.0, but was not included in Magento 2. In one file (vendor/magento/framework/Xml/Security.php) there is an acknowledgment of the issue:
/**
* If running with PHP-FPM we perform an heuristic scan
* We cannot use libxml_disable_entity_loader because of this bug
* @see https://bugs.php.net/bug.php?id=64938
*/
...but sadly it still calls libxml_disable_entity_loader despite the warning. This is also called in some of the Zend and Symfony components, so it's not really reasonable to handle all these situations. Thus the need for the suggested fix.
Not entirely sure how to fix this in the short-term, as unlike Magento 2 we cannot just edit the bootstrap.php file in Magento 2.1.0. Any suggestions?