summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-02-04 14:20:07 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-02-04 14:20:07 +0900
commit38f9d1e76428bea47c5944c440eab25428c7d99e (patch)
tree1be8cb88a5ee77f2770df402e9023b59ef33e5bf
parentperf(server): improvement of external mediaProxy (#9787) (diff)
downloadmisskey-38f9d1e76428bea47c5944c440eab25428c7d99e.tar.gz
misskey-38f9d1e76428bea47c5944c440eab25428c7d99e.tar.bz2
misskey-38f9d1e76428bea47c5944c440eab25428c7d99e.zip
fix(client): validate urls to improve security
-rw-r--r--CHANGELOG.md7
-rw-r--r--packages/backend/src/server/web/UrlPreviewService.ts8
-rw-r--r--packages/frontend/src/components/MkUrlPreview.vue3
-rw-r--r--packages/frontend/src/components/MkYoutubePlayer.vue3
4 files changed, 19 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0ad1e36213..66382cac12 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,13 @@
You should also include the user name that made the change.
-->
+## 13.x.x (unreleased)
+
+### Improvements
+
+### Bugfixes
+- Client: validate urls to improve security
+
## 13.3.1 (2023/02/04)
### Bugfixes
diff --git a/packages/backend/src/server/web/UrlPreviewService.ts b/packages/backend/src/server/web/UrlPreviewService.ts
index 1bf88fe434..57461b7a33 100644
--- a/packages/backend/src/server/web/UrlPreviewService.ts
+++ b/packages/backend/src/server/web/UrlPreviewService.ts
@@ -73,6 +73,14 @@ export class UrlPreviewService {
});
this.logger.succ(`Got preview of ${url}: ${summary.title}`);
+
+ if (summary.url && !(summary.url.startsWith('http://') || summary.url.startsWith('https://'))) {
+ throw new Error('unsupported schema included');
+ }
+
+ if (summary.player?.url && !(summary.player.url.startsWith('http://') || summary.player.url.startsWith('https://'))) {
+ throw new Error('unsupported schema included');
+ }
summary.icon = this.wrap(summary.icon);
summary.thumbnail = this.wrap(summary.thumbnail);
diff --git a/packages/frontend/src/components/MkUrlPreview.vue b/packages/frontend/src/components/MkUrlPreview.vue
index f7677faf74..62e58e1553 100644
--- a/packages/frontend/src/components/MkUrlPreview.vue
+++ b/packages/frontend/src/components/MkUrlPreview.vue
@@ -1,7 +1,8 @@
<template>
<div v-if="playerEnabled" :class="$style.player" :style="`padding: ${(player.height || 0) / (player.width || 1) * 100}% 0 0`">
<button :class="$style.disablePlayer" :title="i18n.ts.disablePlayer" @click="playerEnabled = false"><i class="ti ti-x"></i></button>
- <iframe :class="$style.playerIframe" :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen/>
+ <iframe v-if="player.url.startsWith('http://') || player.url.startsWith('https://')" :class="$style.playerIframe" :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" :width="player.width || '100%'" :heigth="player.height || 250" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen/>
+ <span v-else>invalid url</span>
</div>
<div v-else-if="tweetId && tweetExpanded" ref="twitter" :class="$style.twitter">
<iframe ref="tweet" scrolling="no" frameborder="no" :style="{ position: 'relative', width: '100%', height: `${tweetHeight}px` }" :src="`https://platform.twitter.com/embed/index.html?embedId=${embedId}&amp;hideCard=false&amp;hideThread=false&amp;lang=en&amp;theme=${$store.state.darkMode ? 'dark' : 'light'}&amp;id=${tweetId}`"></iframe>
diff --git a/packages/frontend/src/components/MkYoutubePlayer.vue b/packages/frontend/src/components/MkYoutubePlayer.vue
index 50d38a71bd..460b038838 100644
--- a/packages/frontend/src/components/MkYoutubePlayer.vue
+++ b/packages/frontend/src/components/MkYoutubePlayer.vue
@@ -7,9 +7,10 @@
<div class="poamfof">
<Transition :name="$store.state.animation ? 'fade' : ''" mode="out-in">
- <div v-if="player.url" class="player">
+ <div v-if="player.url && (player.url.startsWith('http://') || player.url.startsWith('https://'))" class="player">
<iframe v-if="!fetching" :src="player.url + (player.url.match(/\?/) ? '&autoplay=1&auto_play=1' : '?autoplay=1&auto_play=1')" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen/>
</div>
+ <span v-else>invalid url</span>
</Transition>
<MkLoading v-if="fetching"/>
<MkError v-else-if="!player.url" @retry="ytFetch()"/>