Cms: Sanitize modifier may break json format without double encoding

Created on 4 Jan 2021  路  3Comments  路  Source: statamic/cms

Bug Description

When passing data to a vue component via props, the sanitize modifier does not double encode html characters. I'm not sure what the pro's are of this approach, but one of the cons is that now it becomes impossible to pass bard data containing double quotes to a vue component through a prop.

How to Reproduce

Long way; shown through a vue component

  1. Create a collection with a blueprint that has a bard field (let's say a 'chairs' collection with a bard field).
  2. Create a new chair that has double quotes in the bard field; for example:
    This chair has a beautiful attribute: "Something"
  3. Have a vue component that expects an array as a prop. Inside it just simply try to render the data from the chairs blueprint.
  4. Add the vue component in the template of one of your pages, and pass the chairs down to the vue component through a prop (example: :chairs="{{ chairs | to_json | sanitize }}")

The component will now not render, because the json is invalid.

Short way; just inspect the json

  1. Create a collection with a blueprint that has a bard field (let's say a 'chairs' collection with a bard field).
  2. Create a new chair that has double quotes in the bard field; for example:
    This chair has a beautiful attribute: "Something"
  3. Try to dump the following data in a template: {{ chairs | to_json | sanitize }}

You can now see that the quote "Something" is messing with the json format. Double encoding the data (by modifying the sanitize modifier) fixes the issue.

Extra Detail

Screenshot 2021-01-04 at 22 45 44

Environment

Statamic 3.0.30 Pro
Laravel 7.30.0
PHP 7.4.9

Workaround

The workaround is to create your own modifier that actually double encodes the data. Feels like this should either be an option for the core modifier, or should be the default? Like I said I'm not entirely sure what the impact would be of changing this default.

bug

Most helpful comment

@jelleroorda sent me his custom modifier which works great. Might be of help to others as well:

<?php

namespace App\Modifiers;

use Statamic\Facades\Config;
use Statamic\Modifiers\Modifier;

class SanitizeFixed extends Modifier
{
    /**
     * Modify a value.
     *
     * @param mixed  $value    The value to be modified
     * @return mixed
     */
    public function index($value)
    {
        // We double encode characters, so we don't get any breaking json when we try to feed
        // json containing quotes inside our vue components.
        return htmlspecialchars($value, ENT_QUOTES, Config::get('statamic.system.charset', 'UTF-8'), true);
    }
}

All 3 comments

@jelleroorda sent me his custom modifier which works great. Might be of help to others as well:

<?php

namespace App\Modifiers;

use Statamic\Facades\Config;
use Statamic\Modifiers\Modifier;

class SanitizeFixed extends Modifier
{
    /**
     * Modify a value.
     *
     * @param mixed  $value    The value to be modified
     * @return mixed
     */
    public function index($value)
    {
        // We double encode characters, so we don't get any breaking json when we try to feed
        // json containing quotes inside our vue components.
        return htmlspecialchars($value, ENT_QUOTES, Config::get('statamic.system.charset', 'UTF-8'), true);
    }
}

Sorted! Now you can pass true as an argument on the sanitize modifier and it'll double encode. I didn't want to flip the behavior as default because that could break people's sites.

{{ var | sanitize:true }}

Nice!!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jimblue picture jimblue  路  3Comments

filipac picture filipac  路  4Comments

robdekort picture robdekort  路  3Comments

philippgrimm picture philippgrimm  路  3Comments

sauerbraten picture sauerbraten  路  3Comments