Skip to content

Commit

Permalink
Fix xss vulnerability in the seo component (#1839)
Browse files Browse the repository at this point in the history
* Fix xss vulnerability in the seo component
  • Loading branch information
blittle authored Mar 12, 2024
1 parent 5060cf5 commit 2888014
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/popular-moose-beam.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/hydrogen': patch
---

Fix XSS vulnerability in the SEO component
52 changes: 50 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion packages/hydrogen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@
"dependencies": {
"@shopify/hydrogen-react": "2024.1.1",
"content-security-policy-builder": "^2.1.1",
"type-fest": "^4.5.0"
"type-fest": "^4.5.0",
"xss": "^1.0.15"
},
"peerDependencies": {
"@remix-run/react": "^2.1.0",
Expand Down
11 changes: 10 additions & 1 deletion packages/hydrogen/src/seo/generate-seo-tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type {ComponentPropsWithoutRef} from 'react';
import type {Maybe} from '@shopify/hydrogen-react/storefront-api-types';
import type {Thing, WithContext} from 'schema-dts';

import xss from 'xss';

const ERROR_PREFIX = 'Error in SEO input: ';

// TODO: Refactor this into more reusable validators or use a library like zod to do this if we decide to use it in
Expand Down Expand Up @@ -503,7 +505,14 @@ export function generateSeoTags<
'script',
{
type: 'application/ld+json',
children: JSON.stringify(block),
children: JSON.stringify(block, (k, value) => {
return typeof value === 'string'
? xss(value, {
stripIgnoreTag: true,
stripIgnoreTagBody: true,
})
: value;
}),
},
// @ts-expect-error
`json-ld-${block?.['@type'] || block?.name || index++}`,
Expand Down
29 changes: 29 additions & 0 deletions packages/hydrogen/src/seo/seo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,35 @@ describe('seo', () => {
</DocumentFragment>
`);
});

it('escapes script content', async () => {
vi.mocked(useMatches).mockReturnValueOnce([
fillMatch({
data: {
seo: {
jsonLd: {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Hydrogen Root',
description: '</script><script>alert("hacked")</script>shows up',
},
},
},
}),
]);

const {asFragment} = render(createElement(Seo));

expect(asFragment()).toMatchInlineSnapshot(`
<DocumentFragment>
<script
type="application/ld+json"
>
{"@context":"https://schema.org","@type":"Organization","name":"Hydrogen Root","description":"shows up"}
</script>
</DocumentFragment>
`);
});
});

function fillMatch(partial: Partial<UIMatch<any>> = {}) {
Expand Down

0 comments on commit 2888014

Please sign in to comment.