Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

tobyreed's avatar

Laravel {{!! escaping !!}} is not escaping?

Hello,

I have an issue with my project where a certain string will cause a client side template injection and xss.

This is the string that causes it: qss%7B%7Bq%3d(2*2.0)%7D%7Dqss.

This will render on the other side as: qss4qss.

But the thing is I have no idea why? I have tried using both escaped & not-escaped to see if it would work. Yet they both seem to be showing the same thing and are computing the 2*2.0 within the string.

Any help would be appreciated and hopefully a solution! :)

0 likes
30 replies
tobyreed's avatar

sorry yes. That is the one I used. Sorry for the typo.

Sti3bas's avatar

@tobyreed so {{ "qss%7B%7Bq%3d(2*2.0)%7D%7Dqss" }} will output qss4qss in your template?

tobyreed's avatar

Correct. The same as {!! "qss%7B%7Bq%3d(2*2.0)%7D%7Dqss" !!}.

I will add some more detail as it could be relevant.

This is an input from the previous page. So the blade template is something like this: {!! (old('var', $var)) !!}.

I don't know if this makes a difference but I cannot seem to prevent it!

tobyreed's avatar
tobyreed
OP
Best Answer
Level 5

Okay, so after doing some digging around for a while and taking a look at other resolutions I finally found one that works well but a bit confusingly.

This is what worked for me: {!! htmlspecialchars(old('var', $var)) !!}

I was a little confused as of why this worked. Because I thought laravel blades {{ $var }} was meant to use htmlEntities() but htmlEntities() includes ALL characters which are html. So I thought {{$var}} would be more comprehensive than htmlspecialchars() ??

Oh well, fixed my issue and I hope it fixes someone else's too!

tobyreed's avatar

How would I identify if I am over-riding it?

Would it just be somewhere within my project... as in it could be anywhere?

Sti3bas's avatar

@tobyreed php artisan tinker then type e("qss%7B%7Bq%3d(2*2.0)%7D%7Dqss") and press enter.

1 like
tobyreed's avatar

Interesting.

This gives the correct output that I would WANT?

here's the output:

Psy Shell v0.9.12 (PHP 7.4.0 — cli) by Justin Hileman
>>> e("qss%7B%7Bq%3d(2*2.0)%7D%7Dqss")
=> "qss%7B%7Bq%3d(2*2.0)%7D%7Dqss"
Sti3bas's avatar

@tobyreed what about Blade::compileString('{{ "qss%7B%7Bq%3d(2*2.0)%7D%7Dqss" }}');?

1 like
tobyreed's avatar

I get this:

Psy Shell v0.9.12 (PHP 7.4.0 — cli) by Justin Hileman
>>> Blade::compileString('{{ "qss%7B%7Bq%3d(2*2.0)%7D%7Dqss" }}');
=> "<?php echo e("qss%7B%7Bq%3d(2*2.0)%7D%7Dqss"); ?>"
tobyreed's avatar

Indeed. But if I compile it within my blade file. It still computes it and will give me qss4qss.

tobyreed's avatar

I am not comfortable sharing the entire file but I will share the relevant snippet that I am using.

<md-input-container class="md-block">
            <label>Email</label>
            <input type="hidden"
                   name="email"
                   value="{!! old('email', $email) !!}">
            <input type="email"
                   value="{!! old('email', $email) !!}"
                   disabled />
            @includeWhen($errors->has('email'), 'shared.validation', [
            'message' => $errors->first('email')
            ])
        </md-input-container>

I appreciate your help :)

tobyreed's avatar

If I use either {!! old ('email', $email) !!} or the one shown in the snippet they both do not work.

tobyreed's avatar

I am sure.

There is only one variable being parsed to this blade file and it's the 'email' !

Snapey's avatar

not sure what you are trying to do here exactly, but

qss%7B%7Bq%3d(2*2.0)%7D%7Dqss

evaluates to

qss{{q=(2*2.0)}}qss

in the html, and if you have vue enabled, the q=(2*2.0) will output as 4

Don't really see what this has to do with html special entities??????

tobyreed's avatar

So, I want this to be a sanitized input (because it should not perform the calculation) otherwise it's possible for a client side template injection to happen.

So since Laravel provides a "safe" way to echo out strings parsed to it I used: {{ old('email', $email) }} to begin with (which did not work) it was still showing the calculation was performed and 4 was showing still.

Then I tried without escaping such as the snippet shown above and it didn't work either... the calculation was still performed when I don't want it to be!

Snapey's avatar

its nothing to do with Laravel, you are outputting code which will be interpolated by Vue

None of the characters are 'special' so why should they be affected by php

If you want to avoid vue processing the output you can add a tag for that

tobyreed's avatar

I am not using Vue but instead Angular.

I forgot to mention that I also added a directive onto the field: ng-non-bindable in order to fully sanitize this.

But, I thought the whole use in the {{ }} was to output a safe string that would not be computed as code?

Snapey's avatar

blade does not know that double braces are 'code' and mean something to your front-end !

Sanitization is for HTML (only)

This is how Vue does it https://vuejs.org/v2/api/#v-pre. (not relevant now, I know)

If you cannot prevent angular interpolating the moustaches, I suggest you write a back end function that disables double braces when it sees them in content.

tobyreed's avatar

So then what's the use of these double braces?

https://laravel.com/docs/6.x/blade

Here in the documentation it says that the data is parsed through PHP's htmlspecialchars function which is used to prevent xss attacks.

Yet, the string I gave earlier still evaluated to qss4qss when it should have been prevented?

tobyreed's avatar

Yes, as said. This is what I am using now and it works (using ngNonBindable) on the field.

Snapey's avatar

{{ }} are not special characters

< and > are examples of special characters. Ones that would allow you to write a javascript script tag in the middle of your name for instance

tobyreed's avatar

Yes... but in the documentation the {{ $var }} will prevent xss of $var. But in my case... it didn't?

peeter's avatar

@tobyreed did you find the answer? I have the same question. Why doesn't {{ $var }} prevent the xss of $var? It is supposed to but in my case it didn't either.

Please or to participate in this conversation.