Skip to content

1.2.0

Latest

Choose a tag to compare

@dereuromark dereuromark released this 05 May 02:11
· 12 commits to master since this release
0b1478e

Fixes

  • JSON-LD XSS via </script> breakout. MetaHelper::renderJsonLd() used JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE, so any string value funneled through setBreadcrumbs(), setArticle(), or setOrganization() could contain a literal </script> and break out of the inline JSON-LD script block. A blog/CMS app wiring setArticle(['headline' => $post->title]) was a realistic XSS sink. Flags are now JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT per OWASP "JSON in HTML" guidance — <, >, &, ', " are emitted as \uXXXX escapes.
  • Canonical-URL attribute breakout. getCanonical() did not HTML-escape the URL when it matched the absolute-URL regex. A developer setting setCanonical($entity->user_supplied_url) would interpolate raw input into href="..." via the css link template. The URL is now passed through h() before formatting.

Improvements

  • New JSON-LD structured-data API on MetaHelper for Schema.org markup:
    • setBreadcrumbs() / getBreadcrumbs() — BreadcrumbList
    • setArticle() / getArticle() — Article
    • setOrganization() / getOrganization() — Organization with global config merge support

Usage

// Breadcrumbs
$this->Meta->setBreadcrumbs([
    ['name' => 'Home', 'url' => '/'],
    ['name' => 'Blog', 'url' => '/blog'],
    ['name' => 'My Post'],
]);

// Article
$this->Meta->setArticle([
    'headline' => 'My Article',
    'author' => 'John Doe',
    'datePublished' => '2026-03-19',
]);

// Organization (supports global config)
$this->Meta->setOrganization([
    'name' => 'Acme Inc',
    'url' => 'https://acme.com',
]);

// Automatically included in out()
echo $this->Meta->out();

JSON-LD is pretty-printed in debug mode for readability.

Full Changelog: 1.1.1...1.2.0