Securing Laravel

Share this post

Security Tip: Safely Rendering JSON in Blade

securinglaravel.com

Discover more from Securing Laravel

The essential security resource for Laravel devs, covering everything you need to keep your apps secure. Sign up to receive weekly security tips and monthly in depth articles, diving deep into security concepts you need to know!
Over 2,000 subscribers
Continue reading
Sign in

Security Tip: Safely Rendering JSON in Blade

[Tip#41] It's quite common to inject JSON into Blade templates - but is it safe?

Stephen Rees-Carter
Mar 30, 2023
3
Share this post

Security Tip: Safely Rendering JSON in Blade

securinglaravel.com
6
Share

Greetings my friends! We’re continuing our series of tips covering simple helpers with security benefits by looking at a simple helper function in Laravel for getting JSON safely into Blade templates, without needing to worry about XSS.

I’m excited to let you all know that I launched the next module in Practical Laravel Security today, covering Cross-Site Request Forgery (CSRF) attacks! You can read all the details over here, or if you’ve already signed up, you’ll find it here. I built 6 interactive challenges for this module, which take you through from a basic copy-pasted form, through to abusing a subdomain, and then stealing an unprotected CSRF token. 😎

Please consider becoming a paid subscriber to support Laravel Security in Depth.
You’ll receive weekly security tips and monthly In Depth articles, covering every aspect of building secure applications in Laravel.

👉 Security Audits: Want me to hack your app and help you improve your security? 🕵️

Looking to learn more?
⏩ Security Tip #26: Type Juggling
▶️ In Depth #9: Signed URLs


Safely Rendering JSON in Blade

It’s a pretty common approach to pass data between your backend and frontend through Blade by rendering a block of JSON into a JS variable.

Something like this:

<script>
    var options = <?php echo json_encode($options); ?>;
</script>

However, is this safe?

Well, it depends... In earlier versions of PHP, it wasn’t safe. Now… maybe?

The issue is that `json_encode()` isn’t designed for outputting a safe block of JSON within a script block inside HTML. It’s default encoding only handles a basic subset of special cases, and there is always the risk that a new bypass is discovered that will allow for breaking out of the JSON and injecting a custom script.

Some of my favourites from older versions of PHP include simply using a `</script>` tag or special “quotes” that PHP will ignore but Javascript will translate into standard quotes.

1

So what should you do instead?

Laravel provides a helper class, `Illuminate\Support\Js`

2
, which includes the extra encoding flags you want when using `json_encode()` within HTML.

Using it is trivial:

<script>
    var options = {{ Js::from($options) }};
</script>

It’s super simple to use - in fact it’s even shorter than the previous code - and will ensure no one can sneak anything into your JSON.

To wrap up, let’s review the difference in output - which nicely shows the benefits in using the helper.

<script>
// json_encode();
var options = {"elves":"three","dwarves":"seven","men":"nine","dark lord":"one"};

// Js::from()
var options = JSON.parse('{\u0022elves\u0022:\u0022three\u0022,\u0022dwarves\u0022:\u0022seven\u0022,\u0022men\u0022:\u0022nine\u0022,\u0022dark lord\u0022:\u0022\\u003C\\\/script\\u003E\u0022}');
</script>

QUICK UPDATE: 2023-05-24

A recent addition to Laravel added a new `Js::encode()` helper, which you can use to encode JSON without the addition of `JSON.parse(...)` that `Js::from()` adds.

> Js::encode(['elves' => 'three', 'dwarves' => 'seven']);
= "{"elves":"three","dwarves":"seven"}"

These two helper functions should remove the need to use `@js()` and `@json()` entirely.

Don’t forget, you can put these safely inside `{{ ... }}` tags too!

1

I was very disappointed when none of my tests worked.

2

https://github.com/laravel/framework/blob/10.x/src/Illuminate/Support/Js.php

3
Share this post

Security Tip: Safely Rendering JSON in Blade

securinglaravel.com
6
Share
Previous
Next
6 Comments
Share this discussion

Security Tip: Safely Rendering JSON in Blade

securinglaravel.com
ankurk91
Apr 2Liked by Stephen Rees-Carter

Why you did not mention the @json directive?

Expand full comment
Reply
Share
5 replies by Stephen Rees-Carter and others
5 more comments...
Top
New
Community

No posts

Ready for more?

© 2023 Stephen Rees-Carter
Privacy ∙ Terms ∙ Collection notice
Start WritingGet the app
Substack is the home for great writing