Search code examples
laravellaravel-bladelaravelcollective

LaravelCollective/html escape inconsistency with double curly braces


On Laravel 5.8 I can use double curly braces to escape a string {{ "<script>alert('does not work');</script>" }} or a variable {{ $comment }}

However, if I use LaravelCollective/html package to create html elements, double curly braces doesn't escape anything. {{ Form::input('edit', 'test') }} creates an input.

How does LaravelCollective/html achieve this or is this an exception in Blade syntax itself? Is {{ }} a secure way to escape anything if it's sometimes escaped and sometimes not? Could I make a custom class to fool Laravel into thinking I'm using LaravelCollective/html and get unescaped content printed with the custom class/object with {{ }}?


Solution

  • It seems LaravelCollective/html achieves this by registering a custom handler with BladeCompiler::directive(), so it's an extension feature provided by Blade. As such it's safe to use {{ }} for both escaping and creating html elements with LaravelCollective.

    For reference, here's a snippet from HtmlServiceProvider.php in LaravelCollective/Html for how it's done.

    /**
     * Register Blade directives.
     *
     * @return void
     */
    protected function registerBladeDirectives()
    {
        $this->app->afterResolving('blade.compiler', function (BladeCompiler $bladeCompiler) {
            $namespaces = [
                'Html' => get_class_methods(HtmlBuilder::class),
                'Form' => get_class_methods(FormBuilder::class),
            ];
    
            foreach ($namespaces as $namespace => $methods) {
                foreach ($methods as $method) {
                    if (in_array($method, $this->directives)) {
                        $snakeMethod = Str::snake($method);
                        $directive = strtolower($namespace).'_'.$snakeMethod;
    
                        $bladeCompiler->directive($directive, function ($expression) use ($namespace, $method) {
                            return "<?php echo $namespace::$method($expression); ?>";
                        });
                    }
                }
            }
        });
    }