kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
Sanitize html
rodzic
9ed6213a46
commit
d090adc1f1
|
@ -23,6 +23,7 @@
|
||||||
"axios": "0.27.2",
|
"axios": "0.27.2",
|
||||||
"axios-auth-refresh": "3.3.1",
|
"axios-auth-refresh": "3.3.1",
|
||||||
"diff": "5.1.0",
|
"diff": "5.1.0",
|
||||||
|
"dompurify": "^2.3.8",
|
||||||
"focus-trap": "6.9.4",
|
"focus-trap": "6.9.4",
|
||||||
"fomantic-ui-css": "2.8.8",
|
"fomantic-ui-css": "2.8.8",
|
||||||
"howler": "2.2.3",
|
"howler": "2.2.3",
|
||||||
|
@ -50,6 +51,7 @@
|
||||||
"vuex-router-sync": "5.0.0"
|
"vuex-router-sync": "5.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/dompurify": "^2.3.3",
|
||||||
"@types/jest": "28.1.3",
|
"@types/jest": "28.1.3",
|
||||||
"@types/jquery": "3.5.14",
|
"@types/jquery": "3.5.14",
|
||||||
"@types/lodash-es": "4.17.6",
|
"@types/lodash-es": "4.17.6",
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
<!-- eslint-disable vue/no-v-html
|
|
||||||
We render some markdown to html here, the content is set by the admin so we should be save
|
|
||||||
-->
|
|
||||||
<template>
|
<template>
|
||||||
<main
|
<main
|
||||||
v-title="labels.title"
|
v-title="labels.title"
|
||||||
|
@ -80,9 +77,9 @@ We render some markdown to html here, the content is set by the admin so we shou
|
||||||
About this pod
|
About this pod
|
||||||
</translate>
|
</translate>
|
||||||
</h2>
|
</h2>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="longDescription"
|
v-if="longDescription"
|
||||||
v-html="markdown.makeHtml(longDescription)"
|
:html="markdown.makeHtml(longDescription)"
|
||||||
/>
|
/>
|
||||||
<p v-else>
|
<p v-else>
|
||||||
<translate translate-context="Content/About/Paragraph">
|
<translate translate-context="Content/About/Paragraph">
|
||||||
|
@ -98,9 +95,9 @@ We render some markdown to html here, the content is set by the admin so we shou
|
||||||
Rules
|
Rules
|
||||||
</translate>
|
</translate>
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="rules"
|
v-if="rules"
|
||||||
v-html="markdown.makeHtml(rules)"
|
:html="markdown.makeHtml(rules)"
|
||||||
/>
|
/>
|
||||||
<p v-else>
|
<p v-else>
|
||||||
<translate translate-context="Content/About/Paragraph">
|
<translate translate-context="Content/About/Paragraph">
|
||||||
|
@ -116,9 +113,9 @@ We render some markdown to html here, the content is set by the admin so we shou
|
||||||
Terms and privacy policy
|
Terms and privacy policy
|
||||||
</translate>
|
</translate>
|
||||||
</h3>
|
</h3>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="terms"
|
v-if="terms"
|
||||||
v-html="markdown.makeHtml(terms)"
|
:html="markdown.makeHtml(terms)"
|
||||||
/>
|
/>
|
||||||
<p v-else>
|
<p v-else>
|
||||||
<translate translate-context="Content/About/Paragraph">
|
<translate translate-context="Content/About/Paragraph">
|
||||||
|
@ -444,7 +441,6 @@ export default {
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
// TODO (wvffle): Remove v-html
|
|
||||||
markdown: new showdown.Converter(),
|
markdown: new showdown.Converter(),
|
||||||
showAllowedDomains: false
|
showAllowedDomains: false
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,10 @@
|
||||||
</translate>
|
</translate>
|
||||||
</p>
|
</p>
|
||||||
<template v-if="renderedDescription || rules">
|
<template v-if="renderedDescription || rules">
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="renderedDescription"
|
v-if="renderedDescription"
|
||||||
id="renderedDescription"
|
id="renderedDescription"
|
||||||
v-html="renderedDescription"
|
:html="renderedDescription"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="renderedDescription"
|
v-if="renderedDescription"
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { sanitize } from 'dompurify'
|
||||||
|
import { computed, h } from 'vue'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
tag?: string
|
||||||
|
html: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
tag: 'div'
|
||||||
|
})
|
||||||
|
|
||||||
|
const html = computed(() => sanitize(props.html))
|
||||||
|
const root = () => h(props.tag, { innerHTML: html.value })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<root />
|
||||||
|
</template>
|
|
@ -4,9 +4,9 @@
|
||||||
@submit.prevent="submit"
|
@submit.prevent="submit"
|
||||||
>
|
>
|
||||||
<h3>{{ plugin.label }}</h3>
|
<h3>{{ plugin.label }}</h3>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="plugin.description"
|
v-if="plugin.description"
|
||||||
v-html="markdown.makeHtml(plugin.description)"
|
:html="markdown.makeHtml(plugin.description)"
|
||||||
/>
|
/>
|
||||||
<template v-if="plugin.homepage">
|
<template v-if="plugin.homepage">
|
||||||
<div class="ui small hidden divider" />
|
<div class="ui small hidden divider" />
|
||||||
|
@ -84,9 +84,9 @@
|
||||||
v-model="values[field.name]"
|
v-model="values[field.name]"
|
||||||
type="text"
|
type="text"
|
||||||
>
|
>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="field.help"
|
v-if="field.help"
|
||||||
v-html="markdown.makeHtml(field.help)"
|
:html="markdown.makeHtml(field.help)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -100,9 +100,9 @@
|
||||||
type="text"
|
type="text"
|
||||||
rows="5"
|
rows="5"
|
||||||
/>
|
/>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="field.help"
|
v-if="field.help"
|
||||||
v-html="markdown.makeHtml(field.help)"
|
:html="markdown.makeHtml(field.help)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -115,9 +115,9 @@
|
||||||
v-model="values[field.name]"
|
v-model="values[field.name]"
|
||||||
type="url"
|
type="url"
|
||||||
>
|
>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="field.help"
|
v-if="field.help"
|
||||||
v-html="markdown.makeHtml(field.help)"
|
:html="markdown.makeHtml(field.help)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
@ -130,9 +130,9 @@
|
||||||
v-model="values[field.name]"
|
v-model="values[field.name]"
|
||||||
type="password"
|
type="password"
|
||||||
>
|
>
|
||||||
<div
|
<sanitized-html
|
||||||
v-if="field.help"
|
v-if="field.help"
|
||||||
v-html="markdown.makeHtml(field.help)"
|
:html="markdown.makeHtml(field.help)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -36,9 +36,9 @@
|
||||||
Nothing to preview.
|
Nothing to preview.
|
||||||
</translate>
|
</translate>
|
||||||
</p>
|
</p>
|
||||||
<div
|
<sanitized-html
|
||||||
v-else
|
v-else
|
||||||
v-html="preview"
|
:html="preview"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<template v-if="content && !isUpdating">
|
<template v-if="content && !isUpdating">
|
||||||
<div v-html="html" />
|
<sanitized-html :html="html" />
|
||||||
<template v-if="isTruncated">
|
<template v-if="isTruncated">
|
||||||
<div class="ui small hidden divider" />
|
<div class="ui small hidden divider" />
|
||||||
<a
|
<a
|
||||||
|
|
|
@ -17,9 +17,9 @@
|
||||||
<div class="eight wide left aligned column">
|
<div class="eight wide left aligned column">
|
||||||
<h1 class="ui header">
|
<h1 class="ui header">
|
||||||
{{ track.title }}
|
{{ track.title }}
|
||||||
<div
|
<sanitized-html
|
||||||
class="sub header"
|
class="sub header"
|
||||||
v-html="subtitle"
|
:html="subtitle"
|
||||||
/>
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
<div v-if="markdown && object.summary">
|
<div v-if="markdown && object.summary">
|
||||||
<div class="ui hidden divider" />
|
<div class="ui hidden divider" />
|
||||||
<p><strong><translate translate-context="Content/Moderation/*/Noun">Reason</translate></strong></p>
|
<p><strong><translate translate-context="Content/Moderation/*/Noun">Reason</translate></strong></p>
|
||||||
<div v-html="markdown.makeHtml(object.summary)" />
|
<sanitized-html :html="markdown.makeHtml(object.summary)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ui hidden divider" />
|
<div class="ui hidden divider" />
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="extra text">
|
<div class="extra text">
|
||||||
<expandable-div :content="note.summary">
|
<expandable-div :content="note.summary">
|
||||||
<div v-html="markdown.makeHtml(note.summary)" />
|
<sanitized-html :html="markdown.makeHtml(note.summary)" />
|
||||||
</expandable-div>
|
</expandable-div>
|
||||||
</div>
|
</div>
|
||||||
<div class="meta">
|
<div class="meta">
|
||||||
|
|
|
@ -167,7 +167,7 @@
|
||||||
class="summary"
|
class="summary"
|
||||||
:content="obj.summary"
|
:content="obj.summary"
|
||||||
>
|
>
|
||||||
<div v-html="markdown.makeHtml(obj.summary)" />
|
<sanitized-html :html="markdown.makeHtml(obj.summary)" />
|
||||||
</expandable-div>
|
</expandable-div>
|
||||||
</div>
|
</div>
|
||||||
<aside class="column">
|
<aside class="column">
|
||||||
|
|
|
@ -13,16 +13,17 @@
|
||||||
custom
|
custom
|
||||||
:to="notificationData.detailUrl"
|
:to="notificationData.detailUrl"
|
||||||
>
|
>
|
||||||
<span
|
<sanitized-html
|
||||||
|
tag="span"
|
||||||
class="link"
|
class="link"
|
||||||
@click="navigate"
|
@click="navigate"
|
||||||
@keypress.enter="navigate"
|
@keypress.enter="navigate"
|
||||||
v-html="notificationData.message"
|
:html="notificationData.message"
|
||||||
/>
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div
|
<sanitized-html
|
||||||
v-else
|
v-else
|
||||||
v-html="notificationData.message"
|
:html="notificationData.message"
|
||||||
/>
|
/>
|
||||||
<template v-if="notificationData.acceptFollow">
|
<template v-if="notificationData.acceptFollow">
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ import ActionFeedback from '~/components/common/ActionFeedback.vue'
|
||||||
import RenderedDescription from '~/components/common/RenderedDescription.vue'
|
import RenderedDescription from '~/components/common/RenderedDescription.vue'
|
||||||
import ContentForm from '~/components/common/ContentForm.vue'
|
import ContentForm from '~/components/common/ContentForm.vue'
|
||||||
import InlineSearchBar from '~/components/common/InlineSearchBar.vue'
|
import InlineSearchBar from '~/components/common/InlineSearchBar.vue'
|
||||||
|
import SanitizedHtml from '~/components/SanitizedHtml.vue'
|
||||||
|
|
||||||
export const install: InitModule = ({ app }) => {
|
export const install: InitModule = ({ app }) => {
|
||||||
app.component('HumanDate', HumanDate)
|
app.component('HumanDate', HumanDate)
|
||||||
|
@ -40,4 +41,5 @@ export const install: InitModule = ({ app }) => {
|
||||||
app.component('RenderedDescription', RenderedDescription)
|
app.component('RenderedDescription', RenderedDescription)
|
||||||
app.component('ContentForm', ContentForm)
|
app.component('ContentForm', ContentForm)
|
||||||
app.component('InlineSearchBar', InlineSearchBar)
|
app.component('InlineSearchBar', InlineSearchBar)
|
||||||
|
app.component('SanitizedHtml', SanitizedHtml)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
Support this Funkwhale pod
|
Support this Funkwhale pod
|
||||||
</translate>
|
</translate>
|
||||||
</h4>
|
</h4>
|
||||||
<div v-html="markdown.makeHtml($store.state.instance.settings.instance.support_message.value)" />
|
<sanitized-html :html="markdown.makeHtml($store.state.instance.settings.instance.support_message.value)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="ui bottom attached segment">
|
<div class="ui bottom attached segment">
|
||||||
<form
|
<form
|
||||||
|
|
|
@ -201,7 +201,10 @@
|
||||||
Description
|
Description
|
||||||
</translate>
|
</translate>
|
||||||
</td>
|
</td>
|
||||||
<td v-html="object.artist.description.html" />
|
<sanitized-html
|
||||||
|
tag="td"
|
||||||
|
:html="object.artist.description.html"
|
||||||
|
/>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="object.actor.url">
|
<tr v-if="object.actor.url">
|
||||||
<td>
|
<td>
|
||||||
|
|
|
@ -212,7 +212,10 @@
|
||||||
Description
|
Description
|
||||||
</translate>
|
</translate>
|
||||||
</td>
|
</td>
|
||||||
<td v-html="object.description.html" />
|
<sanitized-html
|
||||||
|
tag="td"
|
||||||
|
:html="object.description.html"
|
||||||
|
/>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -211,7 +211,10 @@
|
||||||
Description
|
Description
|
||||||
</translate>
|
</translate>
|
||||||
</td>
|
</td>
|
||||||
<td v-html="object.description.html" />
|
<sanitized-html
|
||||||
|
tag="td"
|
||||||
|
:html="object.description.html"
|
||||||
|
/>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -277,7 +277,10 @@
|
||||||
Description
|
Description
|
||||||
</translate>
|
</translate>
|
||||||
</td>
|
</td>
|
||||||
<td v-html="object.description.html" />
|
<sanitized-html
|
||||||
|
tag="td"
|
||||||
|
:html="object.description.html"
|
||||||
|
/>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -1363,6 +1363,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/types" "^7.3.0"
|
"@babel/types" "^7.3.0"
|
||||||
|
|
||||||
|
"@types/dompurify@^2.3.3":
|
||||||
|
version "2.3.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.3.3.tgz#c24c92f698f77ed9cc9d9fa7888f90cf2bfaa23f"
|
||||||
|
integrity sha512-nnVQSgRVuZ/843oAfhA25eRSNzUFcBPk/LOiw5gm8mD9/X7CNcbRkQu/OsjCewO8+VIYfPxUnXvPEVGenw14+w==
|
||||||
|
dependencies:
|
||||||
|
"@types/trusted-types" "*"
|
||||||
|
|
||||||
"@types/estree@0.0.39":
|
"@types/estree@0.0.39":
|
||||||
version "0.0.39"
|
version "0.0.39"
|
||||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
|
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
|
||||||
|
@ -1496,7 +1503,7 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
|
resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1"
|
||||||
integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
|
integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==
|
||||||
|
|
||||||
"@types/trusted-types@^2.0.2":
|
"@types/trusted-types@*", "@types/trusted-types@^2.0.2":
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
|
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
|
||||||
integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
|
integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
|
||||||
|
@ -2905,6 +2912,11 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
domelementtype "^2.3.0"
|
domelementtype "^2.3.0"
|
||||||
|
|
||||||
|
dompurify@^2.3.8:
|
||||||
|
version "2.3.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f"
|
||||||
|
integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw==
|
||||||
|
|
||||||
domutils@^2.5.2, domutils@^2.8.0:
|
domutils@^2.5.2, domutils@^2.8.0:
|
||||||
version "2.8.0"
|
version "2.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
|
resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||||
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue