diff --git a/.changeset/26664-print-under-default-csp.md b/.changeset/26664-print-under-default-csp.md new file mode 100644 index 00000000000..92101118420 --- /dev/null +++ b/.changeset/26664-print-under-default-csp.md @@ -0,0 +1,12 @@ +--- +'@objectstack/service-print': patch +--- + +fix(service-print): a server print works under the console's default Content Security Policy + +Clause-②: no +Metadata-protocol: none + +Every server print (`POST /api/v1/print/records`, `printRecordToFile`) failed on a deployment that keeps the console's default CSP, answering "The print engine failed … page.waitForFunction: EvalError: Evaluating a string as JavaScript violates the following Content Security Policy directive". The Chromium driver waited for the print page with a string predicate, which playwright-core evaluates with `eval` in the page on every poll; the console's `script-src` carries no `'unsafe-eval'` unless `OS_PAGE_REACT_ENABLED` is on, so the second poll was refused. + +The driver now hands the wait a function predicate. playwright-core evaluates a function's text once, inside the DevTools call that starts the wait, which the page's CSP does not govern, and each poll calls the function it produced. The wait means exactly what it meant: a root carrying `data-print-page` and an idle console (`window.__objectui.idle`), held for three polls in a row, polled every 100 ms within the render's one budget. The console CSP is unchanged. diff --git a/packages/services/service-print/src/chromium-driver.test.ts b/packages/services/service-print/src/chromium-driver.test.ts index 9bda5c2f4e4..55cef1c03c9 100644 --- a/packages/services/service-print/src/chromium-driver.test.ts +++ b/packages/services/service-print/src/chromium-driver.test.ts @@ -39,6 +39,15 @@ import type { PrintSessionCookie } from './principal-session.js'; * host's CJK font, every code point mapped; with Chromium's fonts narrowed to a * Latin-only fontconfig, none did. * + * ## Under the console's CSP + * + * The console serves every page with a Content Security Policy whose + * `script-src` carries no `'unsafe-eval'` by default (it is added only for the + * `kind:'react'` page tier, `consoleContentSecurityPolicy` in + * `packages/cli/src/utils/console.ts`). The fixture serves the same print page + * under that directive too, so a ready wait that evaluates a string in the page + * fails here with the EvalError a default deployment answers. + * * ## Which Chromium * * `OS_TEST_PRINT_CHROMIUM_PATH`, else Playwright's provisioned browser @@ -82,12 +91,17 @@ const COOKIE: PrintSessionCookie = { }; const CJK_TEXT = '发票客户名称上海示例有限公司合计金额'; const RECORD_PATH = '/_console/apps/showcase/invoice/record/inv_1'; +/** The same record page, served under the console's default CSP. */ +const CSP_RECORD_PATH = '/_console/apps/showcase/invoice/record/inv_csp'; +const CSP_NONCE = 'print-fixture-nonce'; +/** The console's default `script-src` (no `'unsafe-eval'`), with the rest of its policy's script-relevant directives. */ +const CONSOLE_DEFAULT_CSP = `default-src 'self'; script-src 'self' 'nonce-${CSP_NONCE}' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; object-src 'none'; base-uri 'self'`; -function printPageHtml(): string { +function printPageHtml(nonce?: string): string { return `
-