Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request from GHSA-qhjf-hm5j-335w

* escape html characters in JSON string before injecting it into stream

* Add changeset

---------

Co-authored-by: Lenz Weber-Tronic <lorenz.weber-tronic@apollographql.com>
Co-authored-by: Phil Pluckthun <phil@kitten.sh>

authored by

Jovi De Croock
Lenz Weber-Tronic
Phil Pluckthun
and committed by
GitHub
4b7011b7 b4c46f2d

+31 -1
+5
.changeset/brave-buses-thank.md
··· 1 + --- 2 + '@urql/next': patch 3 + --- 4 + 5 + Fix `CVE-2024-24556`, addressing an XSS vulnerability, where `@urql/next` failed to escape HTML characters in JSON payloads injected into RSC hydration bodies. When an attacker is able to manipulate strings in the JSON response in RSC payloads, this could cause HTML to be evaluated via a typical XSS vulnerability (See [`GHSA-qhjf-hm5j-335w`](https://github.com/urql-graphql/urql/security/advisories/GHSA-qhjf-hm5j-335w) for details.)
+2 -1
packages/next-urql/src/DataHydrationContext.ts
··· 1 1 import * as React from 'react'; 2 2 import { ServerInsertedHTMLContext } from 'next/navigation'; 3 3 import type { UrqlResult } from './useUrqlValue'; 4 + import { htmlEscapeJsonString } from './htmlescape'; 4 5 5 6 interface DataHydrationValue { 6 7 isInjecting: boolean; ··· 19 20 20 21 function transportDataToJS(data: any) { 21 22 const key = 'urql_transport'; 22 - return `(window[Symbol.for("${key}")] ??= []).push(${JSON.stringify(data)})`; 23 + return `(window[Symbol.for("${key}")] ??= []).push(${htmlEscapeJsonString(JSON.stringify(data))})`; 23 24 } 24 25 25 26 export const DataHydrationContextProvider = ({
+24
packages/next-urql/src/htmlescape.ts
··· 1 + // -------------------------------------------------------------------------------- 2 + // 3 + // copied from 4 + // https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts 5 + // License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md 6 + // 7 + // -------------------------------------------------------------------------------- 8 + 9 + // This utility is based on https://github.com/zertosh/htmlescape 10 + // License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE 11 + 12 + const ESCAPE_LOOKUP: { [match: string]: string } = { 13 + "&": "\\u0026", 14 + ">": "\\u003e", 15 + "<": "\\u003c", 16 + "\u2028": "\\u2028", 17 + "\u2029": "\\u2029", 18 + }; 19 + 20 + export const ESCAPE_REGEX = /[&><\u2028\u2029]/g; 21 + 22 + export function htmlEscapeJsonString(str: string): string { 23 + return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]); 24 + }