Problem/Motivation

Hello, while inspecting some request logs, I noticed a number of unexpected requests with hex-encoded query strings. At first, I attributed these strange URLs to poorly implemented bots/crawlers, but then discovered that, in fact, our JSON-LD output is actually suggesting those bad URLs to begin with!

Here is a shortened sample of our JSON-LD output to demonstrate the problem. Notice the value of .@graph[0].potentialAction.target.urlTemplate; particularly, the query string:

Actual:    ?language=en\u0026keyword=%7Bsearch_term_string%7D
Expected:  ?language=en&keyword={search_term_string}
{
    "@context": "https://schema.org",
    "@graph": [
        {
            "@type": "WebSite",
            "@id": "https://example.com/#website",
            "name": "My Website",
            "url": "https://example.com/",
            "potentialAction": {
                "@type": "SearchAction",
                "target": {
                    "@type": "EntryPoint",
                    "urlTemplate": "https://example.com/search?language=en\u0026keyword=%7Bsearch_term_string%7D"
                },
                "query-input": "required name=search_term_string"
            },
            "publisher": {
                "@type": "MedicalOrganization",
                "@id": "https://example.com/#org"
            }
        },
    ]
}

The problem is that SchemaMetatagManager::encodeJsonld calls json_encode with a number of inappropriate flags, like so:

json_encode($items, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_UNESCAPED_UNICODE);

In most Drupal scenarios, that would be necessary since hex-encoding is needed within HTML attributes, such as data-dialog-options.

However, when the JSON is placed inside a <script type="application/ld+json> tag, the JSON is interpreted literally and hex-encoding isn't necessary.

Steps to reproduce

TBD

Proposed resolution

Call json_encode with only the JSON_PRETTY_PRINT and JSON_UNESCAPED_UNICODE (see why) flags and without JSON_UNESCAPED_SLASHES.

The html_tag render element also needs to not XSS filter the output since that will HTML encode the ampersands (since they won't be hex-encoded)… which is also why JSON_UNESCAPED_SLASHES must be omitted. It prevents user input from escaping the script tag with </script>

Remaining tasks

User interface changes

API changes

Data model changes

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

gabesullice created an issue. See original summary.

gabesullice’s picture

Issue summary: View changes
gabesullice’s picture

Issue summary: View changes
gabesullice’s picture

Issue summary: View changes
gabesullice’s picture

Issue summary: View changes
gabesullice’s picture

Issue summary: View changes
gabesullice’s picture

Issue summary: View changes

echechulina made their first commit to this issue’s fork.

echechulina’s picture

Status: Active » Needs review
Issue tags: +Chicago2026