mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-25 15:12:08 -05:00
Explicitly deny bad URLs.
Fixes #252. Handle embed untrusted links better.
This commit is contained in:
parent
66289911ba
commit
81379d6ec4
5 changed files with 26 additions and 22 deletions
|
@ -1,5 +1,5 @@
|
||||||
.embed {
|
.embed {
|
||||||
margin: .2em 0;
|
margin: 0.2em 0;
|
||||||
|
|
||||||
iframe {
|
iframe {
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -87,26 +87,30 @@
|
||||||
.footer {
|
.footer {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.image {
|
img.image {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: unified actions css (see attachment.module.scss for other actions css)
|
// TODO: unified actions css (see attachment.module.scss for other actions css)
|
||||||
.actions {
|
.actions {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template:
|
grid-template:
|
||||||
"name open" auto
|
"name open" auto
|
||||||
"size open" auto
|
"size open" auto
|
||||||
/ minmax(20px, 1fr) min-content;
|
/ minmax(20px, 1fr) min-content;
|
||||||
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
column-gap: 12px;
|
column-gap: 12px;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
overflow: none;
|
overflow: none;
|
||||||
|
@ -119,7 +123,7 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.filesize {
|
.filesize {
|
||||||
grid-area: size;
|
grid-area: size;
|
||||||
|
|
||||||
|
|
|
@ -111,14 +111,11 @@ export default function Embed({ embed }: Props) {
|
||||||
{embed.title && (
|
{embed.title && (
|
||||||
<span>
|
<span>
|
||||||
<a
|
<a
|
||||||
onClick={(e) =>
|
onMouseDown={(ev) =>
|
||||||
openLink(e.currentTarget.href) &&
|
(ev.button === 0 || ev.button === 1) &&
|
||||||
e.preventDefault()
|
openLink(embed.url)
|
||||||
}
|
}
|
||||||
href={embed.url}
|
className={styles.title}>
|
||||||
target={"_blank"}
|
|
||||||
className={styles.title}
|
|
||||||
rel="noreferrer">
|
|
||||||
{embed.title}
|
{embed.title}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -159,9 +156,7 @@ export default function Embed({ embed }: Props) {
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
onClick={() => openScreen({ id: "image_viewer", embed })}
|
onClick={() => openScreen({ id: "image_viewer", embed })}
|
||||||
onMouseDown={(ev) =>
|
onMouseDown={(ev) => ev.button === 1 && openLink(embed.url)}
|
||||||
ev.button === 1 && window.open(embed.url, "_blank")
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,11 +151,9 @@ export default function Intermediate(props: Props) {
|
||||||
id: "external_link_prompt",
|
id: "external_link_prompt",
|
||||||
link: link.href,
|
link: link.href,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
return true;
|
window.open(link.href, "_blank", "noreferrer");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,16 @@ import { dispatch } from "../../../redux";
|
||||||
|
|
||||||
import Modal from "../../../components/ui/Modal";
|
import Modal from "../../../components/ui/Modal";
|
||||||
|
|
||||||
|
import { useIntermediate } from "../Intermediate";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
link: string;
|
link: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExternalLinkModal({ onClose, link }: Props) {
|
export function ExternalLinkModal({ onClose, link }: Props) {
|
||||||
|
const { openLink } = useIntermediate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
visible={true}
|
visible={true}
|
||||||
|
@ -18,7 +22,7 @@ export function ExternalLinkModal({ onClose, link }: Props) {
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
window.open(link, "_blank", "noreferrer");
|
openLink(link);
|
||||||
onClose();
|
onClose();
|
||||||
},
|
},
|
||||||
confirmation: true,
|
confirmation: true,
|
||||||
|
@ -40,7 +44,8 @@ export function ExternalLinkModal({ onClose, link }: Props) {
|
||||||
domain: url.hostname,
|
domain: url.hostname,
|
||||||
});
|
});
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
window.open(link, "_blank", "noreferrer");
|
|
||||||
|
openLink(link);
|
||||||
onClose();
|
onClose();
|
||||||
},
|
},
|
||||||
plain: true,
|
plain: true,
|
||||||
|
|
|
@ -52,7 +52,9 @@ export function determineLink(href?: string): LinkType {
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
|
|
||||||
if (!internal && url) {
|
if (!internal && url) {
|
||||||
return { type: "external", href, url };
|
if (url.protocol !== "javascript") {
|
||||||
|
return { type: "external", href, url };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue