Fix: reject root-relative .. segments and warn per scan

Dot-segment hrefs like /../outside.css could leave the project, and a process-wide warning set hid missing-sheet notices on later detectHtml calls.

AI assistance: implemented with Cursor Grok 4.6.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Abdul Wahab
2026-08-25 19:47:54 +05:00
co-authored by Cursor
parent 2b88aa5231
commit daae1d4117
2 changed files with 21 additions and 4 deletions
@@ -964,13 +964,14 @@ function buildStaticWindow(staticDoc) {
};
}
const warnedMissingStylesheets = new Set();
function resolveLinkedCssPath(fileDir, href) {
const stripped = href.split(/[?#]/)[0];
const rootRelative = stripped.startsWith('/') && !stripped.startsWith('//');
if (!rootRelative) return path.resolve(fileDir, stripped);
const rel = stripped.replace(/^\/+/, '');
// Drop "." and reject ".." so /../outside.css cannot walk out of dir.
const segments = stripped.replace(/^\/+/, '').split(/[/\\]/).filter(p => p && p !== '.');
if (segments.some(p => p === '..')) return path.join(fileDir, segments.filter(p => p !== '..').join(path.sep));
const rel = segments.join(path.sep);
let dir = fileDir;
for (;;) {
const parent = path.dirname(dir);
@@ -990,6 +991,7 @@ function resolveLinkedCssPath(fileDir, href) {
function collectStaticCssText(root, fileDir, profile, filePath, modules) {
const styleTexts = [];
const warnedMissingStylesheets = new Set();
for (const styleEl of modules.selectAll('style', root.children || [])) {
styleTexts.push(modules.domutils.textContent(styleEl));
}