{"record":{"id":"5f7b739b7c128789","repo":"pbakaus/impeccable","slug":"impeccable-detector-core-unavailable-reason","errorCode":null,"errorMessage":"[impeccable] detector core unavailable: ${reason} (a Content-Security-Policy without 'wasm-unsafe-eval' blocks WebAssembly)","messagePattern":"\\[impeccable\\] detector core unavailable: (.+?) \\(a Content-Security-Policy without 'wasm-unsafe-eval' blocks WebAssembly\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browser-bundle/50-scan.js","lineNumber":21,"sourceCode":"// marshalling), and the extension-mode message loop of the standalone\n// bundle. Ported from cli/engine/browser/injected/index.mjs Section 7; every\n// rule decision is a call into the WASM core (`__impeccable.*`), the DOM\n// reads it needs go through the probe, the overlay UI is 40-overlay.js and\n// the visual-contrast sampling 35-visual.js.\n\nconst IS_BROWSER = typeof window !== 'undefined';\n\n// ─── Section 7: Browser UI (IS_BROWSER only) ────────────────────────────────\n\nif (IS_BROWSER && !__impeccable) {\n  // The core could not start (in practice: a Content-Security-Policy whose\n  // script-src lacks 'wasm-unsafe-eval'). Keep the API surface so callers get\n  // one clear error instead of \"impeccableDetect is not a function\".\n  const reason = __impeccableInitError && __impeccableInitError.message\n    ? __impeccableInitError.message\n    : String(__impeccableInitError);\n  const message = `[impeccable] detector core unavailable: ${reason} (a Content-Security-Policy without 'wasm-unsafe-eval' blocks WebAssembly)`;\n  const fail = () => { throw new Error(message); };\n  const _myScript = document.currentScript;\n  const EXTENSION_MODE = (_myScript && _myScript.dataset.impeccableExtension === 'true')\n    || document.documentElement.dataset.impeccableExtension === 'true';\n  console.warn(message);\n  window.impeccableDetect = fail;\n  window.impeccableDetectAsync = async () => fail();\n  window.impeccableScan = fail;\n  window.impeccableScanAsync = async () => fail();\n  window.impeccableMeasureHiddenText = fail;\n  window.impeccableCollectVisualContrastCandidates = fail;\n  window.impeccableAnalyzeVisualContrast = async () => fail();\n  window.impeccableGetLastVisualContrastAnalyses = () => [];\n  window.__impeccableCoreError = message;\n  if (EXTENSION_MODE) {\n    window.addEventListener('message', (e) => {\n      if (e.source !== window || !e.data || e.data.source !== 'impeccable-command') return;\n      if (e.data.action === 'scan') window.postMessage({ source: 'impeccable-error', message }, '*');\n    });","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/browser-bundle/50-scan.js#L3-L39","documentation":"The impeccable detector core (a WebAssembly module) failed to initialize, most often because the page's Content-Security-Policy script-src lacks 'wasm-unsafe-eval', which Chrome requires for WASM instantiation. The bundle deliberately keeps the documented API surface (window.impeccableDetect, impeccableScan, etc.) as functions that throw this one clear error, instead of leaving them undefined or failing obscurely. A console.warn with the same message is emitted at load time.","triggerScenarios":"Any call to window.impeccableDetect, impeccableDetectAsync, impeccableScan, or impeccableScanAsync after the core's init threw (typically a CSP violation during WebAssembly.instantiate). The underlying reason string is embedded in the message.","commonSituations":"Embedding the detector script on a site with a strict CSP that was not updated for WASM; serving the detector from an extension page whose CSP differs; testing locally behind a security-hardened CSP template.","solutions":["Add 'wasm-unsafe-eval' to the script-src (and worker-src if applicable) directive of the page's Content-Security-Policy","Check console.warn output at script load for the underlying __impeccableInitError reason and fix that root cause first","If you embed the detector in your own extension, ensure the page/extension CSP permits WebAssembly compilation","Verify the core .wasm asset is served from an allowed origin beside the script"],"exampleFix":"// before (meta tag)\n<meta http-equiv=\"Content-Security-Policy\" content=\"script-src 'self'\">\n// after\n<meta http-equiv=\"Content-Security-Policy\" content=\"script-src 'self' 'wasm-unsafe-eval'\">","handlingStrategy":"try-catch","validationCode":"function detectorUsable() {\n  return typeof window.impeccableDetect === 'function' &&\n    !document.querySelector('meta[http-equiv=\"Content-Security-Policy\"][content*:not(*wasm-unsafe-eval)]');\n}\n// simplest pre-check: verify CSP allows wasm\nconst csp = document.querySelector('meta[http-equiv=\"Content-Security-Policy\"]')?.content || '';\nconst cspAllowsWasm = !csp || csp.includes('wasm-unsafe-eval');","typeGuard":"function hasDetector(w) { return typeof w.impeccableDetect === 'function' && typeof w.impeccableScan === 'function'; }","tryCatchPattern":"try {\n  const findings = window.impeccableDetect();\n} catch (e) {\n  if (String(e.message).includes('detector core unavailable')) {\n    console.warn('CSP blocks WASM; add wasm-unsafe-eval to script-src');\n  }\n}","preventionTips":["Always include 'wasm-unsafe-eval' in CSP templates used with the detector","Listen for the load-time console.warn before relying on the API","Feature-check window.impeccableDetect is callable before calling it","Test the detector behind your production CSP, not just locally"],"tags":["csp","webassembly","browser-extension"],"backgroundTag":"module-init-failed","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}