Learn about SecureSmarty introduced in Sugar 14.1

Hi Devs,

In our 14.1 webinar (watch recording), we introduced SecureSmarty a safer alternative to Smarty templates in Sugar.

For further insights, Sugar Engineer Alexander Tatulchenkov, provides additional details and perspectives on this effort:

Why did we add SecureSmarty?

SugarCRM takes system security very seriously. As most Sugar developers know, we frequently update the list of restricted functions/methods/classes that can be used in custom code loaded into Sugar using Module Loadble Packages to address potential threats. We will also frequently provide safe alternatives that our developer community can use.

In Sugar 14.1, we are beginning the process to restrict the use of Smarty (Sugar_Smarty) code and are offering a new alternative called SecureSmarty.

What is changing in Sugar 14.2?

Starting from Sugar 14.2.0 the following classes will be forbidden in MLPs by default:

  • Smarty

  • Sugar_Smarty

  • SugarpdfSmarty

This means that you can’t create an instance or extend any of these classes. If a Sugar MLP includes these classes, then it will not successfully install in Sugar 14.2 and future versions by default.

You can enable them back until Sugar 15.1.0 ( disable this SecureSmarty feature) using enforceSecureSmarty feature flag:

$sugar_config['moduleInstaller']['features']['enforceSecureSmarty'] = false;

Disabling SecureSmarty enforcement is not recommend.

How do I use SecureSmarty?

 You should adapt your existing or future MLP code to use our secure alternative - Sugarcrm\Sugarcrm\Security\MLP\Alternatives\Sugar_Smarty

SecureSmarty feature enforces the usage of secure Smarty settings and prevents dangerous features like 'eval', 'fetch', 'include_php', 'math', 'php', and 'template_object'.

It wraps securely pre-configured Sugar_Smarty class and hides its methods and properties that can be used to disable security policy and applies validation on fetch and display methods to prevent tricks with string: and eval:

To simplify the adoption of secure alternatives SugarCRM used the following approach:

  • The name of the secure alternative is the same as the name of the corresponding function/method/class

  • To use the secure alternative instead of the original function/method/class it should be enough just to import the alternative with a use construction.

e.g. We have an MLP that relies on Sugar_Smarty:

<?php 
// ... 
// the rest of the code is omitted for bravity 
$ss = new Sugar_Smarty(); 
$ss->assign('message', 'Hello world'); 
$ss->display();
To make it safe and compatible with the latest Module Loader checks you may import Sugarcrm\Sugarcrm\Security\MLP\Alternatives\Sugar_Smarty as follows:
<?php 
// Importing secure alternative 
use Sugarcrm\Sugarcrm\Security\MLP\Alternatives\Sugar_Smarty; 

// ... 
// the rest of the code is omitted for bravity 
$ss = new Sugar_Smarty(); 
$ss->assign('message', 'Hello world'); 
$ss->display('/path/to/template.tpl');
Note:

Due to security reasons, you are not able to extend Sugarcrm\Sugarcrm\Security\MLP\Alternatives\Sugar_Smarty class because it’s declared as final. If you need to customize its behavior you should rely on the composition instead:

<?php
use Sugarcrm\Sugarcrm\Security\MLP\Alternatives\Sugar_Smarty;

class MySmarty
{
    public function __construct(private Sugar_Smarty $smarty)
    {}

    /**
     * Customizing the assign method
     * @param $tpl_var
     * @param $value
     * @param $nocache
     * @return void
     */
    public function assign($tpl_var, $value = null, $nocache = false)
    {
        if ($tpl_var === 'message') {
            $value = 'Good buy!';
        }
        $this->smarty->assign($tpl_var, $value, $nocache);
    }

    /**
     * Proxy all other methods to the SecureSmarty object
     * @param string $name
     * @param array $arguments
     * @return mixed
     */
    public function __call(string $name, array $arguments)
    {
        return call_user_func_array([$this->smarty, $name], $arguments);
    }
} 
$ss = new MySmarty(new Sugar_Smarty());
$ss->assign('message', 'Hello world');
$ss->display('/path/to/template.tpl');