X
410336

[gallery] in an event body breaks the JSON-LD: raw tabs land in the description string, so the schema fails to parse

SUMMARY

The method get_schema in EVO_Cal_Event_Structure_Schema builds the JSON-LD block by string
concatenation. It interpolates the event description, the post title and the location address
directly into JSON string literals without JSON-encoding them.

Any character that is illegal inside a JSON string, and any closing SCRIPT tag, produces a block
that does not parse. Google discards a malformed JSON-LD block wholesale rather than partially,
so the event silently loses its structured data.

The most important case needs no unusual content at all. An event body containing the core
WordPress gallery shortcode emits invalid JSON-LD.

HOW TO REPRODUCE

1. Create an event whose body contains nothing but the core gallery shortcode, in square brackets,
with the word gallery followed by an ids attribute listing four attachment IDs.
2. View the event on the front end.
3. Extract the block of type application slash ld plus json and run it through any JSON parser.

The parser reports: Invalid control character, at roughly line 10 column 227.

the Google Rich Results Test on the same URL reports no Event detected.

ROOT CAUSE

Lines 43 to 45 are the only sanitization applied to the description before it is interpolated:

line 43 str_replace of an apostrophe with an apostrophe
line 44 str_replace of a double quote with an apostrophe
line 45 preg_replace of carriage return or line feed with a space

Then line 236 concatenates the result straight into the JSON, as the description key followed by
a colon and the raw variable between two double quotes.

BY: Renato Bonomini - Jul 31,2026 AT 8:04PM - 1 day ago
    • Renato Bonomini Jul 31,2026 AT 8:06PM - Posted 1 day ago - #410337

      `class-calendar-event-schema.php`, lines 43-45, are the only sanitization applied to the description before it is interpolated:


      “`php

      43   $__schema_desc = str_replace(”’”,”’”, $__schema_desc);   // no-op, both sides identical

      44   $__schema_desc = str_replace(’”’,”’”, $__schema_desc);

      45   $__schema_desc = preg_replace( ”/r|n/”, ” ”, $__schema_desc );

      “`


      Then line 236:


      “`php

      236   ”description”:”’.$__schema_desc.’”’.

      “`


      Three problems with that sanitizer:


      1. Line 43 is a no-op. Both arguments to `str_replace` are the identical ASCII apostrophe, so it replaces `’` with `’`. It looks like it was meant to be an entity or a curly quote.

      2. Line 45 strips `r` and `n` but **no other control character**. `t` (`U+0009`) and every other `U+0000`-`U+001F` codepoint pass straight through into a JSON string literal, where they are illegal per RFC 8259 §7.

      3. Nothing handles `</script>`. Line 44 turning `”` into `’` does not help, since `</script>` contains no quotes.


      Line 176 has the same defect for the location address:


      “`php

      176   $_schema_location .= ‘{”@type”:”Place”,’.$_name.’”address”:{”@type”: ”PostalAddress”,”streetAddress”:”’. str_replace(”,”,”,”, stripslashes($location_address) ).’”}}’;

      “`


      `$location_address` comes from `event_location` term meta and is interpolated with no control-character handling at all.


      The post title at line 231 goes through `htmlspecialchars(…, ENT_QUOTES)`, which handles quotes but likewise passes control characters through untouched.

You must login to reply to this ticket

HelpDesk

Welcome to EventON helpdesk.

EventON is the #1 Best selling event calendar plugin for WordPress websites in envato marketplace.

Checkout EventON