fix(server): use `xss` to serialize data
Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
parent
81d49f0893
commit
93f58ecfd8
|
|
@ -34,7 +34,8 @@
|
|||
"satori": "0.11.2",
|
||||
"sonner": "^1.5.0",
|
||||
"tailwindcss": "3.4.14",
|
||||
"use-context-selector": "2.0.0"
|
||||
"use-context-selector": "2.0.0",
|
||||
"xss": "1.0.15"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@follow/components": "workspace:*",
|
||||
|
|
@ -45,14 +46,12 @@
|
|||
"@follow/types": "workspace:*",
|
||||
"@follow/utils": "workspace:*",
|
||||
"@radix-ui/react-avatar": "1.1.1",
|
||||
"@types/serialize-javascript": "5.0.4",
|
||||
"daisyui": "4.12.13",
|
||||
"foxact": "0.2.39",
|
||||
"lightningcss": "1.27.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"masonic": "4.0.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"serialize-javascript": "6.0.2",
|
||||
"tailwindcss": "3.4.14",
|
||||
"tsup": "8.3.0",
|
||||
"tsx": "4.19.1",
|
||||
|
|
|
|||
|
|
@ -1,18 +1,4 @@
|
|||
import serialize from "serialize-javascript"
|
||||
|
||||
function escapeHtml(unsafe?: string | null) {
|
||||
if (!unsafe) {
|
||||
return unsafe
|
||||
}
|
||||
|
||||
return unsafe
|
||||
.replaceAll("&", "&")
|
||||
.replaceAll("<", "<")
|
||||
.replaceAll(">", ">")
|
||||
.replaceAll('"', """)
|
||||
.replaceAll("'", "'")
|
||||
.replaceAll("/", "/")
|
||||
}
|
||||
import xss from "xss"
|
||||
|
||||
export function buildSeoMetaTags(configs: {
|
||||
openGraph: {
|
||||
|
|
@ -22,25 +8,23 @@ export function buildSeoMetaTags(configs: {
|
|||
}
|
||||
}) {
|
||||
const openGraph = {
|
||||
title: escapeHtml(configs.openGraph.title),
|
||||
description: escapeHtml(configs.openGraph.description),
|
||||
image: escapeHtml(configs.openGraph.image),
|
||||
title: xss(configs.openGraph.title),
|
||||
description: xss(configs.openGraph.description ?? ""),
|
||||
image: xss(configs.openGraph.image ?? ""),
|
||||
}
|
||||
const title = `${openGraph.title} | Follow`
|
||||
return [
|
||||
`<meta property="og:title" content="${serialize(title)}" />`,
|
||||
`<meta property="og:title" content="${title}" />`,
|
||||
openGraph.description
|
||||
? `<meta property="og:description" content="${serialize(openGraph.description)}" />`
|
||||
? `<meta property="og:description" content="${openGraph.description}" />`
|
||||
: "",
|
||||
openGraph.image ? `<meta property="og:image" content="${serialize(openGraph.image)}" />` : "",
|
||||
openGraph.image ? `<meta property="og:image" content="${openGraph.image}" />` : "",
|
||||
// Twitter
|
||||
`<meta property="twitter:card" content="summary_large_image" />`,
|
||||
`<meta property="twitter:title" content="${serialize(title)}" />`,
|
||||
`<meta property="twitter:title" content="${title}" />`,
|
||||
openGraph.description
|
||||
? `<meta property="twitter:description" content="${serialize(openGraph.description)}" />`
|
||||
: "",
|
||||
openGraph.image
|
||||
? `<meta property="twitter:image" content="${serialize(openGraph.image)}" />`
|
||||
? `<meta property="twitter:description" content="${openGraph.description}" />`
|
||||
: "",
|
||||
openGraph.image ? `<meta property="twitter:image" content="${openGraph.image}" />` : "",
|
||||
].join("\n")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { env } from "@follow/shared/env"
|
|||
import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"
|
||||
import { parseHTML } from "linkedom"
|
||||
import { FetchError } from "ofetch"
|
||||
import serialize from "serialize-javascript"
|
||||
import xss from "xss"
|
||||
|
||||
import { isDev } from "~/lib/env"
|
||||
import { buildSeoMetaTags } from "~/lib/seo"
|
||||
|
|
@ -119,14 +119,12 @@ async function injectMetaToTemplate(template: string, req: FastifyRequest) {
|
|||
break
|
||||
}
|
||||
case "meta": {
|
||||
allMetaString.push(
|
||||
`<meta property="${meta.property}" content="${serialize(meta.content)}" />`,
|
||||
)
|
||||
allMetaString.push(`<meta property="${meta.property}" content="${xss(meta.content)}" />`)
|
||||
break
|
||||
}
|
||||
case "title": {
|
||||
if (meta.title) {
|
||||
template = template.replace(`<!-- TITLE -->`, `${serialize(meta.title)} | Follow`)
|
||||
template = template.replace(`<!-- TITLE -->`, `${xss(meta.title)} | Follow`)
|
||||
isTitleReplaced = true
|
||||
}
|
||||
break
|
||||
|
|
@ -137,7 +135,7 @@ async function injectMetaToTemplate(template: string, req: FastifyRequest) {
|
|||
const script = document.createElement("script")
|
||||
script.innerHTML = `
|
||||
window.__HYDRATE__ = window.__HYDRATE__ || {}
|
||||
window.__HYDRATE__['${meta.key}'] = ${serialize(meta.data)}
|
||||
window.__HYDRATE__['${meta.key}'] = ${xss(JSON.stringify(meta.data))}
|
||||
`
|
||||
document.head.append(script)
|
||||
template = document.toString()
|
||||
|
|
|
|||
|
|
@ -730,6 +730,9 @@ importers:
|
|||
use-context-selector:
|
||||
specifier: 2.0.0
|
||||
version: 2.0.0(react@18.3.1)(scheduler@0.23.2)
|
||||
xss:
|
||||
specifier: 1.0.15
|
||||
version: 1.0.15
|
||||
devDependencies:
|
||||
'@follow/components':
|
||||
specifier: workspace:*
|
||||
|
|
@ -755,9 +758,6 @@ importers:
|
|||
'@radix-ui/react-avatar':
|
||||
specifier: 1.1.1
|
||||
version: 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@types/serialize-javascript':
|
||||
specifier: 5.0.4
|
||||
version: 5.0.4
|
||||
daisyui:
|
||||
specifier: 4.12.13
|
||||
version: 4.12.13(patch_hash=igsntdatmoaxzwxof4bkkh35fy)(postcss@8.4.47)
|
||||
|
|
@ -776,9 +776,6 @@ importers:
|
|||
react-dom:
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1(react@18.3.1)
|
||||
serialize-javascript:
|
||||
specifier: 6.0.2
|
||||
version: 6.0.2
|
||||
tsup:
|
||||
specifier: 8.3.0
|
||||
version: 8.3.0(jiti@2.3.3)(postcss@8.4.47)(tsx@4.19.1)(typescript@5.6.3)(yaml@2.6.0)
|
||||
|
|
@ -4383,9 +4380,6 @@ packages:
|
|||
'@types/semver@7.5.8':
|
||||
resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
|
||||
|
||||
'@types/serialize-javascript@5.0.4':
|
||||
resolution: {integrity: sha512-Z2R7UKFuNWCP8eoa2o9e5rkD3hmWxx/1L0CYz0k2BZzGh0PhEVMp9kfGiqEml/0IglwNERXZ2hwNzIrSz/KHTA==}
|
||||
|
||||
'@types/shimmer@1.2.0':
|
||||
resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==}
|
||||
|
||||
|
|
@ -5397,6 +5391,9 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
cssfilter@0.0.10:
|
||||
resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==}
|
||||
|
||||
cssnano-preset-default@7.0.6:
|
||||
resolution: {integrity: sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==}
|
||||
engines: {node: ^18.12.0 || ^20.9.0 || >=22.0}
|
||||
|
|
@ -8992,9 +8989,6 @@ packages:
|
|||
resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
serialize-javascript@6.0.2:
|
||||
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
|
||||
|
||||
server-only@0.0.1:
|
||||
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
|
||||
|
||||
|
|
@ -9970,6 +9964,11 @@ packages:
|
|||
resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
||||
xss@1.0.15:
|
||||
resolution: {integrity: sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==}
|
||||
engines: {node: '>= 0.10.0'}
|
||||
hasBin: true
|
||||
|
||||
xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
|
|
@ -14284,8 +14283,6 @@ snapshots:
|
|||
|
||||
'@types/semver@7.5.8': {}
|
||||
|
||||
'@types/serialize-javascript@5.0.4': {}
|
||||
|
||||
'@types/shimmer@1.2.0': {}
|
||||
|
||||
'@types/tar@6.1.13':
|
||||
|
|
@ -15555,6 +15552,8 @@ snapshots:
|
|||
|
||||
cssesc@3.0.0: {}
|
||||
|
||||
cssfilter@0.0.10: {}
|
||||
|
||||
cssnano-preset-default@7.0.6(postcss@8.4.47):
|
||||
dependencies:
|
||||
browserslist: 4.23.3
|
||||
|
|
@ -19876,10 +19875,6 @@ snapshots:
|
|||
type-fest: 0.13.1
|
||||
optional: true
|
||||
|
||||
serialize-javascript@6.0.2:
|
||||
dependencies:
|
||||
randombytes: 2.1.0
|
||||
|
||||
server-only@0.0.1: {}
|
||||
|
||||
set-blocking@2.0.0: {}
|
||||
|
|
@ -20853,6 +20848,11 @@ snapshots:
|
|||
|
||||
xmlbuilder@15.1.1: {}
|
||||
|
||||
xss@1.0.15:
|
||||
dependencies:
|
||||
commander: 2.20.3
|
||||
cssfilter: 0.0.10
|
||||
|
||||
xtend@4.0.2: {}
|
||||
|
||||
y18n@5.0.8: {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue