Volt's absolute path

I probably found a bug inside compile of Volt\Compiler.

I have special task, which is going to throw all templates and compile them. I found, that there is problem woith some templtaes, which have inside absulute include macro. These macros are looking in / not in templates root directory.

$compiler = new \Phalcon\Mvc\View\Engine\Volt\Compiler();
$compiler->setOptions(array(
'compiledPath' => $this->cacheDir,
'compiledExtension' => '.php',
'compiledSeparator' => '_'
// 'compileAlways' => true
));
chdir($someDirectoryCloseToTemplate);
$compiler->compile($fileName);

And I have inside volt template something like:

{% include "/partials/header.volt" %}

compile is going to look for /partials/header.volt on root / which is not good. It should definitely look just in templates root.

Am I missing something?

P.S.: task is much more complicated, there is just few lines from her.

You have a leading slash. Change your include path to:

{% include "partials/header.volt" %}

Are you expecting, when I use slash /, that it's ok to use include for:

{% include "/etc/passwd" %}

Imagine that stupid programmer, who will have there variable

{% include $_GET['subpage'] %}
or
$_GET['subpage'] = '../../app/config/config.ini';
{% include $_GET['subpage'] %}

How hard is it to hack?



7.0k

I think, you have wrong setup server and (or) application. Your example

{% include "/etc/passwd" %}

doesn't work.

Output :

Phalcon\Mvc\View\Exception : 
Template file /home/userhttp/projects/Sample/Apps/Backend/Views//etc/passwd does not exist

Here is real task, which is called from CLI. The problem is, that generated template really contains /etc/passwd.

This Task basically go throw all volt templates and generate php. Then I use ngettext to extract strings.

The chdir and getcwd is hack, to start working templates generation, because Phalcon don't have any templateRoot.

<?php

class GenerateVoltTemplatesTask extends \Phalcon\CLI\Task
{

    private $cacheDir;

    public function mainAction()
    {
        $this->compileDirectory(APPLICATION_PATH . '/views');
    }

    /**
     * Compiles
     * @param path
     */
    private function compileDirectory($path)
    {
        echo "$path \n";
        // Create a compiler
        $compiler = new \Phalcon\Mvc\View\Engine\Volt\Compiler();
        $compiler->setOptions(array(
            'compiledPath' => $this->cacheDir,
            'compiledExtension' => '.php',
            'compiledSeparator' => '_'
        // 'compileAlways' => true
                ));
        $compiler->addFunction('_', '_');

        $compiler->addFunction('strtotime', function ($resolvedArgs, $exprArgs)
        {
            return 'strtotime(' . $resolvedArgs . ')';
        });

        $baseDir = getcwd();
        $objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS | RecursiveIteratorIterator::LEAVES_ONLY));

        $i = 0;
        // go throw all volt files and compile them
        foreach ($objects as $name => $object)
        {
            if ($object->getExtension() !== 'volt')
                continue;
            echo $object->getBasename() . " ";
            try
            {
                chdir($baseDir);
                $newFilename = $this->optimizePath($name, getcwd());
                $newFilename = substr($newFilename, 1);
                $compiler->compile($newFilename);
            }
            catch (\Exception $e)
            {
                echo "\nERROR 1: " . $e->getMessage();
                try
                {
                    chdir(dirname($object->getPath()));
                    $newFilename = $this->optimizePath($name, getcwd());
                    $newFilename = substr($newFilename, 1);
                    $compiler->compile($newFilename);
                }
                catch (\Exception $e)
                {
                    echo "\nERROR 2: " . $e->getMessage();
                    try
                    {
                        chdir(dirname($object->getPath()));

                        $newFilename = $this->optimizePath($name, getcwd());
                        $newFilename = substr($newFilename, 1);
                        $compiler->compile($newFilename);
                    }
                    catch (\Exception $e)
                    {
                        echo "\nERROR 3: " . $e->getMessage();
                        continue;
                    }
                }
            }

            echo "\n -> " . $compiler->getCompiledTemplatePath() . "\n";
            $i ++;
        }
        chdir($baseDir);
        echo "Templates compiled: $i\n\n";
    }

    private function optimizePath($filename, $directory)
    {
        return str_replace($directory, '', $filename);
    }
}


7.0k

I mean that CLI application Phalcon is not for web using. Therefore there is no security threat. You can use chroot for your CLI application also for more safety.