Improving the security of files uploaded to Sugar

When users can upload arbitrary files to an application, it poses a considerable security risk when those files are stored on the file system. For instance, a user might unknowingly upload a file containing an executable script by a malicious source, in addition to legitimate files such as images or CSVs from other sources. This presents a security threat that we are addressing in Sugar solutions.

We introduced a file encoding mechanism in the Sugar 12.2 release which significantly improves security by preventing such exploits from happening. With this mechanism in place, any uploaded file is automatically encoded to reduce the likelihood of malicious files being executed on the host system. This enhancement is an essential step towards ensuring the safety and integrity of our application, and we encourage all users to take advantage of this added security feature.

We’ve been utilizing this feature in SugarCloud for a few months now and we would like to share some valuable lessons learned with you. Especially for those of you running on-premise environments like Sugar Enterprise.

When upgrading to versions 12.2, 11.0.6, 12.0.3 and 13.0, we noticed that the SugarUpgradeEncodeUploadFiles upgrade script could take several hours to complete. For some customers, it couldn’t be completed successfully. After some investigation, we found out that upload directories larger than 500GBs were being affected. upload directories using less than 500GBs were fine. Here’s why:

The approach we took on Sugar Upgrader script was to scan all the files in the uploads directory and run the encoding all-at-once regardless of the size. That proved to work for most of our SugarCloud customers, but those 500GB+ (even TB+) instances have led us to come up with an alternative that I’m happy to share with our community in case you need it. 

If you have a Sugar on-premise instance with a 500GB+ filesystem, follow those instructions before running the upgrade process, and as always, it’s a good practice to perform such upgrades on Cloned/Sandboxes if available:

  • Rename the upload directory to upload_tmp (mv upload upload_tmp)
  • Create a new upload directory (mkdir upload)
  • Run the upgrade process as you normally would (note it will still “encode” the upload folder, but now in an empty folder).
  • Post-upgrade, rename back upload_tmp to upload (rm -rf upload & mv upload_tmp upload)
  • Run this standalone script for encoding the upload dir files at your convenience (over the weekend, during the night, or any time that works best for you).
    • This is a CLI PHP script, which means you need to create it, give exec permission, and trigger it from the Sugar instance.
      • vi Encode_uploads_with_progress.php (paste the contents of the script down below)
      • chmod +x Encode_uploads_with_progress.php
      • php Encode_uploads_with_progress.php
    • You will notice that this script provides some feedback on how many files it has processed until it finishes.



use Sugarcrm\Sugarcrm\Util\Files\FilePhpEntriesConverter;
define('sugarEntry', 'upgrade');


if(!in_array("upload", stream_get_wrappers())) {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(UploadStream::getDir()));
$fileConverter = new FilePhpEntriesConverter();

/** @var SplFileInfo $fileInfo */
echo "Starting conversion", PHP_EOL;
$filesProcessed = 0;
foreach ($iterator as $fileInfo) {
    if ($fileInfo->isDir()) {

    $path = $fileInfo->getPathname();
    $encPath = $fileConverter->convert($path);
    rename($encPath, $path);
    if ($filesProcessed % 1000 === 0) {
        echo 'Processed ' . $filesProcessed . ' files.', PHP_EOL;
echo 'Done', PHP_EOL;

  • This is already the case as of version 12:

    The sub-directories are based on the GUID value (I think a substring of the first section) of the uploaded file which keeps the directories evenly populated by randomised design!

    I guess when you have managed to work through your enormous upgrade pathway (saw your other post on the subject Slight smile ) you can take advantage of it.



  • It would be great if the upload directory could be subdivided at some point into subdirectories.

    Some thoughts that come to mind is to do so by Module and within that by year/month.
    Right now ours is big enough (139MB) that it causes stat errors when emails with attachments are processed by the Inbound Email scheduler. Things like:

    Warning [2]: stat(): stat failed for upload/9e5938cc-d976-11ed-8956-001a4a160345 in /var/www/html/sugarcrm/include/upload_file.php on line 936

    There is also a data quality issue, those of us with custom Documents modules for things like Contracts, would love to keep those separate from all the junk png's from email signatures that turn into a myriad of attachments when emails are received and things like case attachments which could be deleted after a certain amount of time.

    Maybe there is already a good way to segment things, but I have not found one. Please let me know if there is, even if it involves coding.

    I remember working with Angel Magaña back in 2015 testing some options
    but we never did get it fully working - or at least not while I was trying it (I am "Unknown" in that thread).