Skip to content

Commit

Permalink
Merge branch 'debug-runner-responses' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
caugner committed Feb 21, 2025
2 parents ed27dde + 2c90113 commit acdb339
Showing 1 changed file with 24 additions and 16 deletions.
40 changes: 24 additions & 16 deletions libs/play/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,9 @@ function playSubdomain(hostname) {
}

/**
* @param {URL} referer
* @param {string} hostname
*/
function isMDNReferer(referer) {
const { hostname } = referer;
function isMDNHost(hostname) {
return (
hostname === ORIGIN_MAIN ||
hostname === ORIGIN_REVIEW ||
Expand All @@ -354,7 +353,9 @@ function isMDNReferer(referer) {
export async function handleRunner(req, res) {
const url = new URL(req.url, "https://example.com");
if (url.searchParams.has("blank")) {
return res.setHeader("Content-Type", "text/html").status(204).end();
// Avoid HTTP 204, because it might break things in Safari:
// "(...) the client **doesn't need to navigate away from its current page**."
return res.setHeader("Content-Type", "text/html").status(200).end();
}
const referer = new URL(
req.headers["referer"] || "https://example.com",
Expand All @@ -370,25 +371,32 @@ export async function handleRunner(req, res) {
const { state, hash } = await decompressFromBase64(stateParam);

if (!state) {
console.warn("[runner] Invalid state parameter");
res.status(404).end();
return;
console.warn("[runner] Invalid state value");
return res.status(404).end();
}

if (req.hostname !== "localhost") {
const expectedHash = playSubdomain(req.hostname);
// For security reasons, we only allow the runner:
// 1. on localhost (without any restrictions),
// 2. if the subdomain matches the hash (for embedded direct links), or
// 3. in iframes on MDN.
const subdomain = playSubdomain(req.hostname);

if (expectedHash !== hash) {
console.warn(
`[runner] Hash mismatch: ${JSON.stringify({ expectedHash, hash })}`
);
if (subdomain !== hash) {
const secFetchDest = req.headers["sec-fetch-dest"];

if (secFetchDest !== "iframe") {
console.warn(
`[runner] Disallowed Sec-Fetch-Dest (expected "iframe", was ${JSON.stringify(secFetchDest)})`
);
return res.status(403).end();
}

const isOnMDN = isMDNReferer(referer);
const isIframe = req.headers["sec-fetch-dest"] === "iframe";
const { hostname } = referer;

if (!isOnMDN || !isIframe) {
if (!isMDNHost(hostname)) {
console.warn(
`[runner] No iframe on MDN: ${JSON.stringify({ isOnMDN, isIframe })}`
`[runner] Disallowed Referer (expected MDN host, was ${JSON.stringify(hostname)})`
);
return res.status(403).end();
}
Expand Down

0 comments on commit acdb339

Please sign in to comment.