From 68552610c76e32e2be37d9ab6991aeda64654682 Mon Sep 17 00:00:00 2001 From: Ricardo Devis Agullo Date: Fri, 5 Sep 2025 08:15:13 +0200 Subject: [PATCH 1/4] add nonce --- src/oc-client.js | 7 +++++++ tests/addStylesToHead.spec.js | 18 ++++++++++++++++ tests/security.spec.js | 39 +++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/src/oc-client.js b/src/oc-client.js index af8d9cc..e63753f 100644 --- a/src/oc-client.js +++ b/src/oc-client.js @@ -38,6 +38,7 @@ export function createOc(oc) { let renderedComponents = oc.renderedComponents; let dataRenderedAttribute = "data-rendered"; let dataRenderingAttribute = "data-rendering"; + let nonce = ocConf.nonce; let logError = (msg) => console.log(msg); let logInfo = (msg) => ocConf.debug && console.log(msg); let handleFetchResponse = (response) => { @@ -124,6 +125,9 @@ export function createOc(oc) { for (let attribute of Array.from(script.attributes)) { newScript.setAttribute(attribute.name, attribute.value); } + if (nonce) { + newScript.setAttribute("nonce", nonce); + } script.parentNode?.replaceChild(newScript, script); } }; @@ -140,6 +144,9 @@ export function createOc(oc) { oc.addStylesToHead = (styles) => { let style = $document.createElement("style"); style.textContent = styles; + if (nonce) { + style.setAttribute("nonce", nonce); + } $document.head.appendChild(style); }; diff --git a/tests/addStylesToHead.spec.js b/tests/addStylesToHead.spec.js index 9034029..fc0f996 100644 --- a/tests/addStylesToHead.spec.js +++ b/tests/addStylesToHead.spec.js @@ -18,4 +18,22 @@ test.describe("oc-client : addStylesToHead", () => { }); expect(style).toEqual("body: {background: red;}"); }); + + test("should set nonce on style tag when cspNonce is provided", async ({ + page, + }) => { + const result = await page.evaluate(() => { + oc.conf.cspNonce = "test-style-nonce"; + oc.addStylesToHead("body { color: black; }"); + const styles = document.head.querySelectorAll("style"); + const last = styles[styles.length - 1]; + return { + nonce: last.getAttribute("nonce"), + content: last.textContent, + }; + }); + + expect(result.nonce).toBe("test-style-nonce"); + expect(result.content).toBe("body { color: black; }"); + }); }); diff --git a/tests/security.spec.js b/tests/security.spec.js index 664fc3f..b1b88f4 100644 --- a/tests/security.spec.js +++ b/tests/security.spec.js @@ -301,4 +301,43 @@ test.describe("oc-client : security and script handling", () => { } } }); + + test("should set nonce on re-animated script when cspNonce is provided", async ({ + page, + }) => { + const result = await page.evaluate(() => { + return new Promise((resolve) => { + oc.conf.cspNonce = "test-script-nonce"; + const component = document.createElement("oc-component"); + component.setAttribute("href", "//oc-registry.com/nonce-test/"); + document.body.appendChild(component); + + // Stub renderByHref to return HTML with a script that records its nonce + const originalRenderByHref = oc.renderByHref; + oc.renderByHref = (opts, cb) => { + cb(null, { + html: '
Content
', + version: "1.0.0", + name: "nonce-test", + key: "nonce-key", + }); + }; + + oc.renderNestedComponent(component, () => { + const script = component.querySelector("script"); + const data = { + attrNonce: script?.getAttribute("nonce"), + currentScriptNonce: window.nonceFromCurrentScript, + }; + // cleanup + oc.renderByHref = originalRenderByHref; + component.remove(); + resolve(data); + }); + }); + }); + + expect(result.attrNonce).toBe("test-script-nonce"); + expect(result.currentScriptNonce).toBe("test-script-nonce"); + }); }); From 45829f1c03e73c081aa607ca5bbb0fcedf9a93c6 Mon Sep 17 00:00:00 2001 From: Ricardo Devis Agullo Date: Fri, 5 Sep 2025 08:40:50 +0200 Subject: [PATCH 2/4] try not saving var --- src/oc-client.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/oc-client.js b/src/oc-client.js index e63753f..75b158a 100644 --- a/src/oc-client.js +++ b/src/oc-client.js @@ -38,7 +38,6 @@ export function createOc(oc) { let renderedComponents = oc.renderedComponents; let dataRenderedAttribute = "data-rendered"; let dataRenderingAttribute = "data-rendering"; - let nonce = ocConf.nonce; let logError = (msg) => console.log(msg); let logInfo = (msg) => ocConf.debug && console.log(msg); let handleFetchResponse = (response) => { @@ -125,8 +124,8 @@ export function createOc(oc) { for (let attribute of Array.from(script.attributes)) { newScript.setAttribute(attribute.name, attribute.value); } - if (nonce) { - newScript.setAttribute("nonce", nonce); + if (ocConf.cspNonce) { + newScript.setAttribute("nonce", ocConf.cspNonce); } script.parentNode?.replaceChild(newScript, script); } @@ -144,8 +143,8 @@ export function createOc(oc) { oc.addStylesToHead = (styles) => { let style = $document.createElement("style"); style.textContent = styles; - if (nonce) { - style.setAttribute("nonce", nonce); + if (ocConf.cspNonce) { + style.setAttribute("nonce", ocConf.cspNonce); } $document.head.appendChild(style); }; From cc01ca4a8c50d5f9eb945501f784cce16b81f970 Mon Sep 17 00:00:00 2001 From: Ricardo Devis Agullo Date: Fri, 5 Sep 2025 09:44:05 +0200 Subject: [PATCH 3/4] add nonce from current --- .vscode/settings.json | 5 +++++ src/oc-client.js | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..795e4bd --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "[javascript]": { + "editor.defaultFormatter": "biomejs.biome" + } +} diff --git a/src/oc-client.js b/src/oc-client.js index 75b158a..a47bd73 100644 --- a/src/oc-client.js +++ b/src/oc-client.js @@ -38,6 +38,8 @@ export function createOc(oc) { let renderedComponents = oc.renderedComponents; let dataRenderedAttribute = "data-rendered"; let dataRenderingAttribute = "data-rendering"; + let nonce = $document.currentScript?.nonce; + let logError = (msg) => console.log(msg); let logInfo = (msg) => ocConf.debug && console.log(msg); let handleFetchResponse = (response) => { @@ -124,8 +126,8 @@ export function createOc(oc) { for (let attribute of Array.from(script.attributes)) { newScript.setAttribute(attribute.name, attribute.value); } - if (ocConf.cspNonce) { - newScript.setAttribute("nonce", ocConf.cspNonce); + if (nonce) { + newScript.setAttribute("nonce", nonce); } script.parentNode?.replaceChild(newScript, script); } @@ -143,8 +145,8 @@ export function createOc(oc) { oc.addStylesToHead = (styles) => { let style = $document.createElement("style"); style.textContent = styles; - if (ocConf.cspNonce) { - style.setAttribute("nonce", ocConf.cspNonce); + if (nonce) { + style.setAttribute("nonce", nonce); } $document.head.appendChild(style); }; From 67c0c4529ac7fe86fa1eb210591c92073c6d1cd7 Mon Sep 17 00:00:00 2001 From: Ricardo Devis Agullo Date: Fri, 5 Sep 2025 09:48:53 +0200 Subject: [PATCH 4/4] remove tests --- tests/addStylesToHead.spec.js | 18 ---------------- tests/security.spec.js | 39 ----------------------------------- 2 files changed, 57 deletions(-) diff --git a/tests/addStylesToHead.spec.js b/tests/addStylesToHead.spec.js index fc0f996..9034029 100644 --- a/tests/addStylesToHead.spec.js +++ b/tests/addStylesToHead.spec.js @@ -18,22 +18,4 @@ test.describe("oc-client : addStylesToHead", () => { }); expect(style).toEqual("body: {background: red;}"); }); - - test("should set nonce on style tag when cspNonce is provided", async ({ - page, - }) => { - const result = await page.evaluate(() => { - oc.conf.cspNonce = "test-style-nonce"; - oc.addStylesToHead("body { color: black; }"); - const styles = document.head.querySelectorAll("style"); - const last = styles[styles.length - 1]; - return { - nonce: last.getAttribute("nonce"), - content: last.textContent, - }; - }); - - expect(result.nonce).toBe("test-style-nonce"); - expect(result.content).toBe("body { color: black; }"); - }); }); diff --git a/tests/security.spec.js b/tests/security.spec.js index b1b88f4..664fc3f 100644 --- a/tests/security.spec.js +++ b/tests/security.spec.js @@ -301,43 +301,4 @@ test.describe("oc-client : security and script handling", () => { } } }); - - test("should set nonce on re-animated script when cspNonce is provided", async ({ - page, - }) => { - const result = await page.evaluate(() => { - return new Promise((resolve) => { - oc.conf.cspNonce = "test-script-nonce"; - const component = document.createElement("oc-component"); - component.setAttribute("href", "//oc-registry.com/nonce-test/"); - document.body.appendChild(component); - - // Stub renderByHref to return HTML with a script that records its nonce - const originalRenderByHref = oc.renderByHref; - oc.renderByHref = (opts, cb) => { - cb(null, { - html: '
Content
', - version: "1.0.0", - name: "nonce-test", - key: "nonce-key", - }); - }; - - oc.renderNestedComponent(component, () => { - const script = component.querySelector("script"); - const data = { - attrNonce: script?.getAttribute("nonce"), - currentScriptNonce: window.nonceFromCurrentScript, - }; - // cleanup - oc.renderByHref = originalRenderByHref; - component.remove(); - resolve(data); - }); - }); - }); - - expect(result.attrNonce).toBe("test-script-nonce"); - expect(result.currentScriptNonce).toBe("test-script-nonce"); - }); });