diff --git a/theme/scripts/screenshot.mjs b/theme/scripts/screenshot.mjs index 5041f4c..420804b 100644 --- a/theme/scripts/screenshot.mjs +++ b/theme/scripts/screenshot.mjs @@ -32,7 +32,7 @@ import { createServer } from 'node:http'; import { copyFileSync, existsSync, mkdirSync, statSync } from 'node:fs'; import { readFile } from 'node:fs/promises'; -import { dirname, extname, join, resolve } from 'node:path'; +import { dirname, extname, join, resolve, sep } from 'node:path'; import { fileURLToPath, pathToFileURL } from 'node:url'; import { chromium } from 'playwright'; @@ -67,7 +67,10 @@ function serveTheme() { try { const url = new URL(req.url, 'http://127.0.0.1'); const target = join(THEME, decodeURIComponent(url.pathname)); - if (!target.startsWith(THEME)) { + /* docroot guard: the prefix must end with a separator — a bare + * startsWith(THEME) lets sibling theme* paths (e.g. a decoded + * ..%2FthemeX) escape the docroot (WR-05). */ + if (target !== THEME && !target.startsWith(THEME + sep)) { res.writeHead(403); res.end('forbidden'); return;