From d29939cdf6c3b46693304de4cd0f2981a0ade6fe Mon Sep 17 00:00:00 2001 From: Florian Vogt Date: Fri, 24 Feb 2023 14:05:56 +0100 Subject: [PATCH 1/3] [FEATURE] CSP: Increase defaultPolicy2 to sap-target-level-3 --- lib/middleware/MiddlewareManager.js | 2 +- lib/server.js | 2 +- test/lib/server/main.js | 8 ++++---- test/lib/server/middleware/MiddlewareManager.js | 6 +++--- test/lib/server/middleware/csp.js | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/middleware/MiddlewareManager.js b/lib/middleware/MiddlewareManager.js index 7990f540..b46e2943 100644 --- a/lib/middleware/MiddlewareManager.js +++ b/lib/middleware/MiddlewareManager.js @@ -184,7 +184,7 @@ class MiddlewareManager { const defaultSAPTargetConfig = { defaultPolicy: "sap-target-level-1", defaultPolicyIsReportOnly: true, - defaultPolicy2: "sap-target-level-2", + defaultPolicy2: "sap-target-level-3", defaultPolicy2IsReportOnly: true, ignorePaths: ["test-resources/sap/ui/qunit/testrunner.html"] }; diff --git a/lib/server.js b/lib/server.js index f5780259..7c857148 100644 --- a/lib/server.js +++ b/lib/server.js @@ -99,7 +99,7 @@ async function _addSsl({app, key, cert}) { * @typedef {object} module:@ui5/server.SAPTargetCSPOptions * @property {string} [defaultPolicy="sap-target-level-1"] * @property {string} [defaultPolicyIsReportOnly=true] - * @property {string} [defaultPolicy2="sap-target-level-2"] + * @property {string} [defaultPolicy2="sap-target-level-3"] * @property {string} [defaultPolicy2IsReportOnly=true] * @property {string[]} [ignorePaths=["test-resources/sap/ui/qunit/testrunner.html"]] */ diff --git a/test/lib/server/main.js b/test/lib/server/main.js index 35d0ead4..c242e50c 100644 --- a/test/lib/server/main.js +++ b/test/lib/server/main.js @@ -420,14 +420,14 @@ test("CSP (defaults)", async (t) => { t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, "header should should have the expected content"); }), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2").then((res) => { + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3").then((res) => { t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s*;/, "header should should have the expected content"); t.is(res.headers["content-security-policy-report-only"], undefined, "response must not have report-only csp header"); }), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2:report-only").then((res) => { + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3:report-only").then((res) => { t.is(res.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); t.truthy(res.headers["content-security-policy-report-only"], @@ -484,8 +484,8 @@ test("CSP (sap policies)", async (t) => { request.get("/index.html"), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1"), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1:report-only"), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2"), - request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2:report-only"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3:report-only"), request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;"), request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;:report-only"), request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;:ro") diff --git a/test/lib/server/middleware/MiddlewareManager.js b/test/lib/server/middleware/MiddlewareManager.js index bfa08b3e..936931a5 100644 --- a/test/lib/server/middleware/MiddlewareManager.js +++ b/test/lib/server/middleware/MiddlewareManager.js @@ -841,7 +841,7 @@ test("addStandardMiddleware: CSP middleware configured correctly (enabled)", asy }, defaultPolicy: "sap-target-level-1", defaultPolicyIsReportOnly: true, - defaultPolicy2: "sap-target-level-2", + defaultPolicy2: "sap-target-level-3", defaultPolicy2IsReportOnly: true, ignorePaths: [ "test-resources/sap/ui/qunit/testrunner.html", @@ -864,7 +864,7 @@ test("addStandardMiddleware: CSP middleware configured correctly (custom)", asyn sendSAPTargetCSP: { defaultPolicy: "sap-target-level-1", defaultPolicyIsReportOnly: false, - defaultPolicy2: "sap-target-level-3", + defaultPolicy2: "sap-target-level-2", defaultPolicy2IsReportOnly: true, ignorePaths: ["lord/tirek.html"] }, @@ -907,7 +907,7 @@ test("addStandardMiddleware: CSP middleware configured correctly (custom)", asyn }, defaultPolicy: "sap-target-level-1", defaultPolicyIsReportOnly: false, - defaultPolicy2: "sap-target-level-3", + defaultPolicy2: "sap-target-level-2", defaultPolicy2IsReportOnly: true, ignorePaths: [ "lord/tirek.html", diff --git a/test/lib/server/middleware/csp.js b/test/lib/server/middleware/csp.js index c184dbe6..b961580a 100644 --- a/test/lib/server/middleware/csp.js +++ b/test/lib/server/middleware/csp.js @@ -56,7 +56,7 @@ test("Default Settings", async (t) => { await new Promise((resolve) => { middleware({ method: "GET", - url: "/test.html?sap-ui-xx-csp-policy=sap-target-level-2", + url: "/test.html?sap-ui-xx-csp-policy=sap-target-level-3", headers: {} }, res, resolve); }); From a7597b537c60582a3bee5bec00c5c37e98fb5cbc Mon Sep 17 00:00:00 2001 From: Matthias Osswald Date: Tue, 28 Feb 2023 13:48:16 +0100 Subject: [PATCH 2/3] [INTERNAL] Enhance CSP tests --- test/lib/server/main.js | 68 ++++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/test/lib/server/main.js b/test/lib/server/main.js index c242e50c..31f5a8d5 100644 --- a/test/lib/server/main.js +++ b/test/lib/server/main.js @@ -420,10 +420,31 @@ test("CSP (defaults)", async (t) => { t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, "header should should have the expected content"); }), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2").then((res) => { + t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); + t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s*;/, + "header should should have the expected content"); + t.regex(res.headers["content-security-policy"], /style-src\s+'self'\s+'unsafe-inline'\s*;/, + "header should should have the expected content"); + t.is(res.headers["content-security-policy-report-only"], undefined, + "response must not have report-only csp header"); + }), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2:report-only").then((res) => { + t.is(res.headers["content-security-policy"], undefined, + "response must not have enforcing csp header"); + t.truthy(res.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should have the expected content"); + t.regex(res.headers["content-security-policy-report-only"], /style-src\s+'self'\s+'unsafe-inline'\s*;/, + "header should have the expected content"); + }), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3").then((res) => { t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s*;/, "header should should have the expected content"); + t.regex(res.headers["content-security-policy"], /style-src\s+'self'\s*;/, + "header should should have the expected content"); t.is(res.headers["content-security-policy-report-only"], undefined, "response must not have report-only csp header"); }), @@ -434,6 +455,8 @@ test("CSP (defaults)", async (t) => { "response should have report-only csp header"); t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, "header should have the expected content"); + t.regex(res.headers["content-security-policy-report-only"], /style-src\s+'self'\s*;/, + "header should have the expected content"); }), request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;").then((res) => { t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); @@ -480,10 +503,15 @@ test("CSP (sap policies)", async (t) => { simpleIndex: false }); - const [result1, result2, result3, result4, result5, result6, result7, result8] = await Promise.all([ + const [ + result1, result2, result3, result4, result5, + result6, result7, result8, result9, result10 + ] = await Promise.all([ request.get("/index.html"), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1"), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1:report-only"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2"), + request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2:report-only"), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3"), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3:report-only"), request.get("/index.html?sap-ui-xx-csp-policy=default-src%20http%3a;"), @@ -495,9 +523,9 @@ test("CSP (sap policies)", async (t) => { t.truthy(result1.headers["content-security-policy-report-only"], "response should have report-only csp header"); t.regex(result1.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should contain the 1st default policy"); - t.regex(result1.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, - "header should contain the 2nd default policy"); + "header should contain the 1st default policy (level-1)"); + t.regex(result1.headers["content-security-policy-report-only"], /style-src\s+'self'\s*;/, + "header should contain the 2nd default policy (level-3)"); t.truthy(result2.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(result2.headers["content-security-policy"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, @@ -528,27 +556,39 @@ test("CSP (sap policies)", async (t) => { "header should have the expected content"); t.truthy(result6.headers["content-security-policy"], "response should have enforcing csp header"); - t.regex(result6.headers["content-security-policy"], /default-src\s+http:\s*;/, - "header should contain the configured policy"); + t.regex(result6.headers["content-security-policy"], /style-src\s+'self'\s*;/, + "header should should have the expected content"); t.regex(result6.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, + "header should contain the level-3 policy"); + + t.is(result7.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); + t.truthy(result7.headers["content-security-policy-report-only"], + "response should have report-only csp header"); + t.regex(result7.headers["content-security-policy-report-only"], /style-src\s+'self'\s*;/, + "header should have the expected content"); + + t.truthy(result8.headers["content-security-policy"], "response should have enforcing csp header"); + t.regex(result8.headers["content-security-policy"], /default-src\s+http:\s*;/, + "header should contain the configured policy"); + t.regex(result8.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, "header should contain the 2nd default policy"); - t.is(result7.headers["content-security-policy"], undefined, + t.is(result9.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); - t.truthy(result7.headers["content-security-policy-report-only"], + t.truthy(result9.headers["content-security-policy-report-only"], "response should have report-only csp header"); - t.regex(result7.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, + t.regex(result9.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, "header should contain the configured policy"); - t.regex(result7.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, + t.regex(result9.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, "header should contain the 2nd default policy"); - t.is(result8.headers["content-security-policy"], undefined, + t.is(result10.headers["content-security-policy"], undefined, "response must not have enforcing csp header"); - t.truthy(result8.headers["content-security-policy-report-only"], + t.truthy(result10.headers["content-security-policy-report-only"], "response should have report-only csp header"); - t.regex(result8.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, + t.regex(result10.headers["content-security-policy-report-only"], /default-src\s+http:\s*;/, "header should contain the configured policy"); - t.regex(result8.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, + t.regex(result10.headers["content-security-policy-report-only"], /default-src\s+'self'\s*;/, "header should contain the 2nd default policy"); await new Promise((resolve, reject) => { From f7bb5317a9116e97d2d63499e940ba74a58af02e Mon Sep 17 00:00:00 2001 From: Matthias Osswald Date: Tue, 28 Feb 2023 14:28:17 +0100 Subject: [PATCH 3/3] [INTERNAL] Fix assertion messages --- test/lib/server/main.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/lib/server/main.js b/test/lib/server/main.js index 31f5a8d5..6a8abe32 100644 --- a/test/lib/server/main.js +++ b/test/lib/server/main.js @@ -408,7 +408,7 @@ test("CSP (defaults)", async (t) => { request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-1").then((res) => { t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.is(res.headers["content-security-policy-report-only"], undefined, "response must not have report-only csp header"); }), @@ -418,14 +418,14 @@ test("CSP (defaults)", async (t) => { t.truthy(res.headers["content-security-policy-report-only"], "response should have report-only csp header"); t.regex(res.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); }), request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-2").then((res) => { t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.regex(res.headers["content-security-policy"], /style-src\s+'self'\s+'unsafe-inline'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.is(res.headers["content-security-policy-report-only"], undefined, "response must not have report-only csp header"); }), @@ -442,9 +442,9 @@ test("CSP (defaults)", async (t) => { request.get("/index.html?sap-ui-xx-csp-policy=sap-target-level-3").then((res) => { t.truthy(res.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(res.headers["content-security-policy"], /script-src\s+'self'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.regex(res.headers["content-security-policy"], /style-src\s+'self'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.is(res.headers["content-security-policy-report-only"], undefined, "response must not have report-only csp header"); }), @@ -529,7 +529,7 @@ test("CSP (sap policies)", async (t) => { t.truthy(result2.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(result2.headers["content-security-policy"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.truthy(result2.headers["content-security-policy-report-only"], "response should have report-only csp header"); t.regex(result2.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, @@ -539,13 +539,13 @@ test("CSP (sap policies)", async (t) => { t.truthy(result3.headers["content-security-policy-report-only"], "response should have report-only csp header"); t.regex(result3.headers["content-security-policy-report-only"], /script-src\s+'self'\s+'unsafe-eval'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.regex(result3.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, "header should contain the 2nd default policy"); t.truthy(result4.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(result4.headers["content-security-policy"], /script-src\s+'self'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.regex(result4.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, "header should contain the 2nd default policy"); @@ -557,7 +557,7 @@ test("CSP (sap policies)", async (t) => { t.truthy(result6.headers["content-security-policy"], "response should have enforcing csp header"); t.regex(result6.headers["content-security-policy"], /style-src\s+'self'\s*;/, - "header should should have the expected content"); + "header should have the expected content"); t.regex(result6.headers["content-security-policy-report-only"], /script-src\s+'self'\s*;/, "header should contain the level-3 policy");