diff options
| author | dakkar <dakkar@thenautilus.net> | 2025-01-02 10:03:16 +0000 |
|---|---|---|
| committer | dakkar <dakkar@thenautilus.net> | 2025-01-02 10:03:16 +0000 |
| commit | ac0c6841aa5a6f6da253235acb58d7f979dd520b (patch) | |
| tree | 0b118777a673a9efd32503c668e0703b44b460f3 /packages/frontend/src/scripts | |
| parent | merge: Add file extension to locally-stored media (!832) (diff) | |
| download | sharkey-ac0c6841aa5a6f6da253235acb58d7f979dd520b.tar.gz sharkey-ac0c6841aa5a6f6da253235acb58d7f979dd520b.tar.bz2 sharkey-ac0c6841aa5a6f6da253235acb58d7f979dd520b.zip | |
use the whole hostname to check remote links - fixes #866
the warning dialog's "trust this domain" toggle saves the whole
hostname, so this code needs to use the whole hostname
otherwise trusting a `www.example.com` will never work, because we'd
be checking `example.com` against it, and fail
while I was there, I also made the `trustedLinkUrlPatterns` correctly
match sub-domains: previously, trusting `ple.com` would trust
`example.com`
Diffstat (limited to 'packages/frontend/src/scripts')
| -rw-r--r-- | packages/frontend/src/scripts/warning-external-website.ts | 20 |
1 files changed, 14 insertions, 6 deletions
diff --git a/packages/frontend/src/scripts/warning-external-website.ts b/packages/frontend/src/scripts/warning-external-website.ts index 67158c6438..0c9b5ba806 100644 --- a/packages/frontend/src/scripts/warning-external-website.ts +++ b/packages/frontend/src/scripts/warning-external-website.ts @@ -8,13 +8,21 @@ import { defaultStore } from '@/store.js'; import * as os from '@/os.js'; import MkUrlWarningDialog from '@/components/MkUrlWarningDialog.vue'; -const extractDomain = /^(https?:\/\/|\/\/)?([^@/\s]+@)?(www\.)?([^:/\s]+)/i; const isRegExp = /^\/(.+)\/(.*)$/; +function extractHostname(maybeUrl: string): URL | null { + try { + const url = new URL(maybeUrl); + return url.host; + } catch { + return null; + } +} + export async function warningExternalWebsite(url: string) { - const domain = extractDomain.exec(url)?.[4]; + const hostname = extractHostname(url); - if (!domain) return false; + if (!hostname) return false; const isTrustedByInstance = instance.trustedLinkUrlPatterns.some(expression => { const r = isRegExp.exec(expression); @@ -24,11 +32,11 @@ export async function warningExternalWebsite(url: string) { } else if (expression.includes(' ')) { return expression.split(' ').every(keyword => url.includes(keyword)); } else { - return domain.endsWith(expression); + return `.${hostname}`.endsWith(`.${expression}`); } }); - const isTrustedByUser = defaultStore.reactiveState.trustedDomains.value.includes(domain); + const isTrustedByUser = defaultStore.reactiveState.trustedDomains.value.includes(hostname); const isDisabledByUser = !defaultStore.reactiveState.warnExternalUrl.value; if (!isTrustedByInstance && !isTrustedByUser && !isDisabledByUser) { @@ -44,7 +52,7 @@ export async function warningExternalWebsite(url: string) { }); if (confirm.canceled) return false; - + return window.open(url, '_blank', 'nofollow noopener popup=false'); } |