Close the browser guard's path-shaped bypass: check-experimental-shelf imported playwright by file path

check-experimental-shelf imported resolve(ROOT, 'node_modules/playwright/index.mjs')
dynamically, named no package specifier, and so launched Chromium outside the
slot while check:browser-gates-guarded passed it (upg100 found and measured it).
It now imports the guard, and an unslotted run exits 75. The check also fails a
path to node_modules/playwright (or playwright-core) anywhere in code; with the
old import restored it fails that file.
This commit is contained in:
Doxa Maps 2026-09-28 08:43:59 +00:00
parent 5a36f17467
commit a9dfe29200
2 changed files with 7 additions and 2 deletions

View file

@ -26,7 +26,10 @@ if (process.argv.includes('--list')) {
// dynamic import or require of the playwright package. The detectors (browser-gates.mjs, this file) spell the
// pattern inside regex literals, escaped, which none of these match, so they need no exclusion and a real
// import added to one still fails. Only the guard itself imports playwright, by design.
const DIRECT = /^\s*import\b[^;\n]*\bfrom\s+['"]playwright['"]|\bimport\(\s*['"]playwright['"]\s*\)|\brequire\(\s*['"]playwright['"]\s*\)/m
// Also a PATH to the package (node_modules/playwright…, or playwright-core) anywhere in code: a gate imported
// resolve(ROOT, 'node_modules/playwright/index.mjs') dynamically, named no specifier, and launched outside the
// slot while this check passed it (upg100 found and measured it).
const DIRECT = /^\s*import\b[^;\n]*\bfrom\s+['"]playwright(?:-core)?['"]|\bimport\(\s*['"]playwright(?:-core)?['"]\s*\)|\brequire\(\s*['"]playwright(?:-core)?['"]\s*\)|node_modules[\/\\]playwright(?:-core)?\b/m
const files = execFileSync('git', ['ls-files', '--', 'internal', 'plugin-designs'], { cwd: ROOT, encoding: 'utf8' })
.split('\n').filter((f) => /\.(mjs|js|cjs)$/.test(f) && f !== 'internal/lib/playwright-guarded.mjs')
const bad = []

View file

@ -70,7 +70,9 @@ const WAIT_MS = Number(process.env.SHELF_WAIT_MS || 75000)
const MIN_COLOURS = Number(process.env.MIN_MAP_COLOURS || 40)
const MIN_FILL = Number(process.env.MIN_MAP_FILL || 0.7)
const { chromium } = await import(resolve(ROOT, 'node_modules/playwright/index.mjs'))
// Through the slot guard like every repo browser gate (it imported node_modules/playwright by path and so
// launched outside the slot; upg100 measured it).
const { chromium } = await import('./lib/playwright-guarded.mjs')
const manifest = JSON.parse(readFileSync(resolve(ROOT, `public/${TREE_NAME}/manifest.json`), 'utf8'))
const spa = readFileSync(resolve(ROOT, 'plugin-designs/doxa-maps-spa/doxa-maps-spa.vue'), 'utf8')
const cfg = JSON.parse(readFileSync(resolve(ROOT, 'vite.doxa-maps-build-config.json'), 'utf8'))