diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61c0748..fa48408 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -187,6 +187,11 @@ jobs: # Also proves the Dockerfile's dist/ sanity checks pass on a real build. - name: Build image run: docker build -t knowledge-base:ci . + # The CSP checks in the container suite need a real browser: a policy that + # blocks something the page needs fails silently, and only a browser + # reports the violation. + - name: Install Playwright browser + run: npx playwright install --with-deps chromium # The only place nginx.conf itself is executed. The other suites run # against tests/fragment-server.mjs, an Express mirror of the rewrites — # see playwright.config.docker.js for why that is not sufficient. diff --git a/AGENTS.md b/AGENTS.md index 1b8d9ec..7dc2264 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -132,6 +132,18 @@ Artifacts come from other repositories' releases. Treat their HTML, CSS and archive contents as attacker-controlled: no unvalidated archive extraction, no unsanitised HTML re-hosting, no shell interpolation of registry values. +### Nothing inline in the output + +The deployment serves `script-src 'self'` with no `'unsafe-inline'`. That holds +only because no inline `\n'); + assert.doesNotMatch(html, /">\n'); + assert.doesNotMatch(html, /javascript:/i); + assert.doesNotMatch(html, /data:text\/html/i); + assert.match(html, /click/, 'link text is kept even though the href is dropped'); + }); + + check('strips inline \n\n

covered

\n'); + assert.doesNotMatch(html, /