Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/Yancy/Editor/src/content-editor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,14 @@
console.debug("editor iframe loaded", e);
channel = new MessageChannel();
channel.port1.onmessage = onmessage;
// Initialize the editor interface by sending the page a MessagePort to use
// Initialize the editor interface by sending the page a MessagePort to use.
// Only send it to the site origin, so pages the iframe navigated away to
// can not get it.
if (e.target instanceof HTMLIFrameElement && e.target.contentWindow) {
e.target.contentWindow.postMessage("Yancy.init", "*", [channel.port2]);
const origin = new URL(e.target.src, window.location.href).origin;
e.target.contentWindow.postMessage("Yancy.init", origin, [
channel.port2,
]);
}
};

Expand Down
36 changes: 31 additions & 5 deletions lib/Yancy/Editor/src/iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,23 @@ import ContentField from "./content-field.svelte";
import { mount } from "svelte";
import "./iframe.css";

const Yancy = (window.Yancy ??= {
allowOrigins: ["http://localhost:3000"],
});
const Yancy = (window.Yancy ??= {});
// By default, only allow an editor on the same origin as this page
Yancy.allowOrigins ??= [window.location.origin];

/**
* Check if the given origin is allowed to control this page. Strings must
* match the origin exactly, and RegExps must match the entire origin.
*/
function isAllowedOrigin(origin: string): boolean {
return (Yancy.allowOrigins ?? []).some((o) => {
if (typeof o === "string") {
return o === origin;
}
const m = origin.match(o);
return m !== null && m.index === 0 && m[0] === origin;
});
}

type YancyEditorMessage = {
name: string;
Expand Down Expand Up @@ -86,6 +100,10 @@ function handleEvent(e: MessageEvent<YancyEditorMessage>) {
let chain = getFocusedEditor().chain();
for (const c of commandEvent.command) {
const [method, ...args] = typeof c === "string" ? [c] : c;
if (typeof chain[method] !== "function") {
console.error(`unknown editor command ${method}`);
return;
}
chain = chain[method](...args);
}
chain.run();
Expand All @@ -94,13 +112,21 @@ function handleEvent(e: MessageEvent<YancyEditorMessage>) {

window.addEventListener("message", (e: MessageEvent) => {
console.debug("got window message", e);
if (!Yancy.allowOrigins.find((o) => e.origin.match(o))) {
// Only handle Yancy editor initialization requests
if (
typeof e.data !== "string" ||
!e.data.startsWith("Yancy.init") ||
!e.ports[0]
) {
return;
}
if (!isAllowedOrigin(e.origin)) {
console.error(`origin ${e.origin} not allowed.`, {
allowOrigins: Yancy.allowOrigins,
});
return;
}

// Handle Yancy editor initialization request
const [, , version] = e.data.split(/:/);
if (version < 0) {
console.error("Yancy editor version not supported by iframe", { version });
Expand Down
Loading