Fix/threads jsonld html script escape#2983
Conversation
Thread JSON-LD can include code samples with </script>. Escaping < as \u003c in serialized JSON prevents the HTML parser from closing script tags early in both the ld+json block and SvelteKit route data. Co-authored-by: Cursor <cursoragent@cursor.com>
…solution - Added support for dynamic hero titles in the marketing page by resolving query parameters. - Introduced new constants for default hero attributes and integrated them into the page logic. - Updated the layout to ensure the document title reflects the hero heading accurately. This improves the SEO and user experience by providing relevant titles based on user context.
Appwrite WebsiteProject ID: Tip GraphQL API works alongside REST and WebSocket protocols |
Greptile SummaryThis PR fixes a script-injection risk where user-supplied content containing
Confidence Score: 4/5The JSON-LD escaping fix is correct and the HTML output is safe; the only real concern is a design inconsistency in how escaping is applied. The escaping logic works correctly end-to-end:
Important Files Changed
|
| }; | ||
|
|
||
| return JSON.stringify(graph); | ||
| return escapeJsonLtForHtmlScript(JSON.stringify(graph)); |
There was a problem hiding this comment.
Pre-escaping creates redundant second pass in
getInlinedScriptTag
createDiscussionForumPageSchema now returns a pre-escaped string (all < replaced with \u003c), but its output is then passed to getInlinedScriptTag, which calls escapeJsonLtForHtmlScript a second time. The second pass is a no-op because no < characters remain, so the HTML output is correct. However, every other schema function (organizationJsonSchema, softwareAppSchema, createPostSchema, etc.) returns raw JSON and relies on getInlinedScriptTag to do the escaping — createDiscussionForumPageSchema is now the only outlier.
If the motivation is to protect structuredDataJsonLd when SvelteKit serializes it into the page's devalue inline script (a separate <script> from the JSON-LD tag), that is a valid concern — but it may be worth a comment at the call site in +page.server.ts explaining why this function pre-escapes while others do not, so future callers of getInlinedScriptTag don't expect all inputs to behave the same way.

What does this PR do?
(Provide a description of what this PR does.)
Test Plan
(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)
Related PRs and Issues
(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)
Have you read the Contributing Guidelines on issues?
(Write your answer here.)