Skip to content

fix: Escape special characters in schema.org JSON-LD metadata#305

Open
tylere wants to merge 2 commits into
mainfrom
claude/escape-schema-json-chars-FQpWP
Open

fix: Escape special characters in schema.org JSON-LD metadata#305
tylere wants to merge 2 commits into
mainfrom
claude/escape-schema-json-chars-FQpWP

Conversation

@tylere
Copy link
Copy Markdown
Contributor

@tylere tylere commented May 7, 2026

What I'm changing

This PR escapes special HTML characters (<, >, &) in schema.org JSON-LD metadata to prevent potential XSS vulnerabilities and ensure proper rendering of structured data on product and account pages.

How I did it

Updated both ProductSchemaMetadata.tsx and AccountSchemaMetadata.tsx to escape special characters in the JSON-LD script content:

  • < is replaced with \u003c
  • > is replaced with \u003e
  • & is replaced with \u0026

This follows security best practices for embedding JSON-LD in HTML documents and prevents any user-supplied data within the schema from breaking out of the script tag.

Also bumped the version to 1.3.0 in package.json to reflect the release.

How you can test it

  1. Navigate to a product page and inspect the page source to verify the schema.org metadata in the <script type="application/ld+json"> tag contains escaped characters where applicable
  2. Navigate to an account/profile page and verify the same escaping is applied
  3. Verify that structured data is still correctly parsed by checking with Google's Rich Results Test or similar schema validation tools
  4. Confirm no visual or functional changes to the pages themselves

https://claude.ai/code/session_01UCrzLXdCiDYw7WKmZ6Ueot

source-release-bot Bot and others added 2 commits May 7, 2026 17:46
Prevents XSS via injected `</script>` or HTML-entity sequences in
account/product fields by encoding `<`, `>`, and `&` as Unicode
escapes within the JSON-LD payload.

https://claude.ai/code/session_01UCrzLXdCiDYw7WKmZ6Ueot
@vercel
Copy link
Copy Markdown

vercel Bot commented May 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
source-cooperative Ready Ready Preview, Comment May 7, 2026 8:31pm

Request Review

@claude
Copy link
Copy Markdown

claude Bot commented May 7, 2026

Claude finished @tylere's task in 1m 53s —— View job


PR Review

Summary: This is a correct, well-scoped security fix. The escaping approach — replacing <, >, and & with their Unicode escape equivalents (<, >, &) — is the standard practice for safely embedding JSON-LD in HTML <script> tags. The Unicode escapes are transparent to JSON parsers but prevent the browser from interpreting them as HTML, eliminating the </script> injection vector.


Security ✅

  • XSS vector closed correctly. The primary risk with dangerouslySetInnerHTML + JSON.stringify is a user-controlled string like </script><script>alert(1)// breaking out of the script tag. Encoding < as < neutralises this completely.
  • & escaping is a bonus. Not strictly required for the injection vector, but it prevents double-encoding issues if the page's HTML parser ever processes the script tag content, and follows the W3C spec recommendation.
  • No over-engineering. The change is minimal and targeted — no new dependencies, no abstraction overhead.

Code Quality — One Note

The escaping chain is identical in both files (see inline comment). Extracting it into a small shared utility (src/lib/jsonLd.ts) would make future changes (e.g. adding ' escaping, or consolidating to a single-pass regex) a one-line edit instead of two. Not a blocker.

Other observations

  • The PR includes a version bump to 1.3.0 (package.json, package-lock.json, CHANGELOG.md) in a separate commit (c862f15). This appears intentional per the PR description. Confirm this is the desired approach rather than cutting a separate 1.3.1 patch after the release lands.

Verdict: Looks good to merge. The fix is correct and the only meaningful suggestion (extracting the shared helper) is a cosmetic follow-up, not a blocker.

Comment on lines +44 to +47
__html: JSON.stringify(schemaData)
.replace(/</g, "\\u003c")
.replace(/>/g, "\\u003e")
.replace(/&/g, "\\u0026"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The identical escaping chain is duplicated in both ProductSchemaMetadata.tsx and AccountSchemaMetadata.tsx. If the escaping logic ever needs to change (e.g., adding ' for ', or switching to a single-pass regex), both files must be updated in sync.

Consider extracting to a shared helper — e.g. src/lib/jsonLd.ts:

export function safeJsonLd(data: unknown): string {
  return JSON.stringify(data)
    .replace(/</g, "\\u003c")
    .replace(/>/g, "\\u003e")
    .replace(/&/g, "\\u0026");
}

Then both components call __html: safeJsonLd(schemaData). Low urgency — the current approach is correct — but worth doing while the logic is fresh. Fix this →

@tylere tylere requested a review from alukach May 7, 2026 20:35
@tylere tylere changed the title Escape special characters in schema.org JSON-LD metadata fix: Escape special characters in schema.org JSON-LD metadata May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants