From ed892885a0d329406398db8d5288b90e927c23b8 Mon Sep 17 00:00:00 2001 From: Yoav Weiss Date: Tue, 8 Apr 2025 05:31:47 -0700 Subject: [PATCH 01/19] Integrity Policy header --- index.bs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/index.bs b/index.bs index 1502f61..d54227a 100644 --- a/index.bs +++ b/index.bs @@ -44,9 +44,17 @@ spec: SHA2; urlPrefix: https://csrc.nist.gov/publications/fips/fips180-4/fips-18 text: SHA-256; url: # text: SHA-384; url: # text: SHA-512; url: # + spec: RFC8288; urlPrefix: https://tools.ietf.org/html/rfc8288 type: http-header text: link + +spec RFC9651; urlPrefix: https://tools.ietf.org/html/rfc9651 + type: dfn + text: Dictionary; url: name-dictionaries + text: inner list; url: name-inner-lists + text: token; url: name-tokens + - To report violation given a Request |request|, a boolean |block|, + To report violation given a Request |request|, a boolean |block|, a boolean |report block|, an integrity policy struct |policy|, and an integrity policy struct |report policy|, do the following: @@ -614,10 +611,11 @@ spec:csp3; type:grammar; text:base64-value 1. Let |settings object| be |request|'s client. 1. Let |global| be |settings object|'s global object. 1. Assert that |global| is a Window or a WorkerGlobalScope. - 1. Let |URL| be an empty URL. - 1. If |global| is a Window, set |URL| to |global|'s associated Document document URL. - 1. If |global| is a WorkerGlobalScope, set |URL| to |global|'s URL. - 1. Let |document URL| be the result of strip URL for use in reports on |URL|. + 1. Let |url| be a URL, initially null. + 1. If |global| is a Window, set |url| to |global|'s associated Document document URL. + 1. If |global| is a WorkerGlobalScope, set |url| to |global|'s URL. + 1. Assert that |url| is a non-null URL. + 1. Let |document URL| be the result of strip URL for use in reports on |url|. 1. Let |blocked URL| be the result of strip URL for use in reports on |request|'s URL. 1. If |block|, for each |endpoint| in |policy|'s endpoints: 1. Let |body| be a new {{IntegrityPolicyViolationReportBody}}, initialized as follows: From 8c43fe8123acefe4fb7edbd4dbcbba386f194c0a Mon Sep 17 00:00:00 2001 From: Yoav Weiss Date: Thu, 1 May 2025 19:28:43 +0200 Subject: [PATCH 15/19] more review comments --- index.bs | 70 +++++++++++++++++++++++--------------------------------- 1 file changed, 28 insertions(+), 42 deletions(-) diff --git a/index.bs b/index.bs index aa198e2..8dcc92e 100644 --- a/index.bs +++ b/index.bs @@ -36,21 +36,6 @@ spec: CSP; urlPrefix: https://www.w3.org/TR/CSP3/ type: dfn text: strip url for use in reports; url: strip-url-for-use-in-reports -spec: DOM; urlPrefix: https://dom.spec.whatwg.org/ - type: dfn - text: document url; url: concept-document-url - -spec: INFRA; urlPrefix: https://infra.spec.whatwg.org - type: dfn - text: list; url: list - -spec: HTML; urlPrefix: https://html.spec.whatwg.org/C - type: dfn - text: policy container; url: policy-container - text: global object; url: global-object - text: window; url: window - text: WorkerGlobalScope; url: workerglobalscope - spec: FETCH; urlPrefix: https://fetch.spec.whatwg.org/ type: dfn text: main fetch; url: main-fetch @@ -531,58 +516,59 @@ spec:csp3; type:grammar; text:base64-value An integrity policy struct, is a struct that contains the following: - * sources, a list of sources, Initially empty. - * blocked destinations, a list of destinations, Initially empty. - * endpoints, a list of strings, initially empty. + * sources, a list of sources, initially empty. + * blocked destinations, a list of destinations, initially empty. + * endpoints, a list of strings, initially empty. When processing an integrity policy, with |headers| and |header name|, do the following: - 1. Let |integrityPolicy| be a new integrity policy struct. + 1. Let |integrity policy| be a new integrity policy struct. 1. Let |dictionary| be the result of getting a structured field value from |headers| given |header name| and "`dictionary`". - 1. If |dictionary|["`sources`"] does not exist or if its value contains "`inline`", - append "`inline`" to |integrityPolicy|'s sources. - 1. If |dictionary|["`blocked-destinations`"] exists: + 1. If |dictionary|["`sources`"] does not exist or if its value + contains "`inline`", append "`inline`" to + |integrity policy|'s sources. + 1. If |dictionary|["`blocked-destinations`"] exists: 1. If its value contains "`script`", - append "`script`" to |integrityPolicy|'s blocked destinations. + append "`script`" to |integrity policy|'s blocked destinations. 1. If |dictionary|["`endpoints`"] exists: - 1. Set |integrityPolicy|'s endpoints to |dictionary|['endpoints']. - 1. Return |integrityPolicy|. + 1. Set |integrity policy|'s endpoints to |dictionary|['endpoints']. + 1. Return |integrity policy|. ### Parse Integrity-Policy headers ### {#parse-integrity-policy-headers-section} To parse Integrity-Policy headers, given a Response |response| - and a policy container |container|, do the following: + and a policy container |container|, do the following: 1. Let |headers| be |response|'s header list. 1. If |headers| contains a header whose header name is "`Integrity-Policy`", - let |container|'s integrity policy be the result of running + set |container|'s integrity policy be the result of running processing an integrity policy with the corresponding header value. 1. If |headers| contains a header whose header name is "`Integrity-Policy-Report-Only`", - let |container|'s report only integrity policy be the result of running + set |container|'s report only integrity policy be the result of running processing an integrity policy with the corresponding header value. ### Should request be blocked by Integrity Policy ### {#should-request-be-blocked-by-integrity-policy-section} To determine should request be blocked by integrity policy, given a request |request|, do the following: - 1. Let |policy container| be |request|'s policy container. - 1. if |request|'s integrity metadata is not the empty string + 1. Let |policy container| be |request|'s policy container. + 1. If |request|'s integrity metadata is not the empty string and |request|'s mode is either "cors" or "same-origin", return "Allowed". 1. Let |policy| be |policy container|'s integrity policy. 1. Let |report policy| be |policy container|'s report only integrity policy. 1. If both |policy| and |report policy| are empty integrity policy structs, return "Allowed". - 1. Let |global| be |request|'s client's global object. - 1. if |global| is not a Window nor a WorkerGlobalScope, return "Allowed". + 1. Let |global| be |request|'s client's global object. + 1. If |global| is not a {{Window}} nor a {{WorkerGlobalScope}}, return "Allowed". 1. Let |block| be a boolean, initially false. 1. Let |report block| be a boolean, initially false. - 1. if |policy|'s sources contains "`inline`" + 1. If |policy|'s sources contains "`inline`" and |policy|'s blocked destinations contains |request|'s destination, set |block| to true. - 1. if |policy|'s sources contains "`inline`" + 1. If |policy|'s sources contains "`inline`" and |report policy|'s blocked destinations contains |request|'s destination, set |report block| to true. @@ -607,14 +593,14 @@ spec:csp3; type:grammar; text:base64-value a boolean |report block|, an integrity policy struct |policy|, and an integrity policy struct |report policy|, do the following: - 1. Assert that |request|'s client is not null. + 1. Assert: |request|'s client is not null. 1. Let |settings object| be |request|'s client. - 1. Let |global| be |settings object|'s global object. - 1. Assert that |global| is a Window or a WorkerGlobalScope. - 1. Let |url| be a URL, initially null. - 1. If |global| is a Window, set |url| to |global|'s associated Document document URL. - 1. If |global| is a WorkerGlobalScope, set |url| to |global|'s URL. - 1. Assert that |url| is a non-null URL. + 1. Let |global| be |settings object|'s global object. + 1. Assert: |global| is a {{Window}} or a {{WorkerGlobalScope}}. + 1. Let |url| be null. + 1. If |global| is a {{Window}}, set |url| to |global|'s associated Document's {{Document/URL}}. + 1. If |global| is a {{WorkerGlobalScope}}, set |url| to |global|'s URL. + 1. Assert: |url| a URL. 1. Let |document URL| be the result of strip URL for use in reports on |url|. 1. Let |blocked URL| be the result of strip URL for use in reports on |request|'s URL. 1. If |block|, for each |endpoint| in |policy|'s endpoints: @@ -658,7 +644,7 @@ spec:csp3; type:grammar; text:base64-value ### Integration ### {#integration} - A policy container has extra items: + A policy container has extra items: * integrity policy, an integrity policy struct. * report only integrity policy, an integrity policy struct. From 0c12600aaecec6d761d9c3241f90092af4cd588b Mon Sep 17 00:00:00 2001 From: Yoav Weiss Date: Tue, 13 May 2025 08:34:37 +0200 Subject: [PATCH 16/19] Make destination a request destination --- index.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.bs b/index.bs index 8dcc92e..2335fa4 100644 --- a/index.bs +++ b/index.bs @@ -512,7 +512,7 @@ spec:csp3; type:grammar; text:base64-value A source is a string. The only possible value for it is "`inline`". - A destination is a string. The only possible value for it is "`script`". + A destination is a destination. The only possible value for it is "`script`". An integrity policy struct, is a struct that contains the following: From 117bb355774575de6ce403b7e91634fe41a03f58 Mon Sep 17 00:00:00 2001 From: Yoav Weiss Date: Wed, 14 May 2025 15:15:35 +0200 Subject: [PATCH 17/19] Review comments --- index.bs | 85 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/index.bs b/index.bs index 2335fa4..597f48a 100644 --- a/index.bs +++ b/index.bs @@ -512,7 +512,7 @@ spec:csp3; type:grammar; text:base64-value A source is a string. The only possible value for it is "`inline`". - A destination is a destination. The only possible value for it is "`script`". + A destination is a string. The only possible value for it is "`script`". An integrity policy struct, is a struct that contains the following: @@ -520,20 +520,21 @@ spec:csp3; type:grammar; text:base64-value * blocked destinations, a list of destinations, initially empty. * endpoints, a list of strings, initially empty. - When processing an integrity policy, with |headers| and |header name|, do the following: + When processing an integrity policy, with a header list |headers| + and a header name |headerName|, do the following: - 1. Let |integrity policy| be a new integrity policy struct. + 1. Let |integrityPolicy| be a new integrity policy struct. 1. Let |dictionary| be the result of getting a structured field value from |headers| - given |header name| and "`dictionary`". + given |headerName| and "`dictionary`". 1. If |dictionary|["`sources`"] does not exist or if its value contains "`inline`", append "`inline`" to - |integrity policy|'s sources. + |integrityPolicy|'s sources. 1. If |dictionary|["`blocked-destinations`"] exists: 1. If its value contains "`script`", - append "`script`" to |integrity policy|'s blocked destinations. + append "`script`" to |integrityPolicy|'s blocked destinations. 1. If |dictionary|["`endpoints`"] exists: - 1. Set |integrity policy|'s endpoints to |dictionary|['endpoints']. - 1. Return |integrity policy|. + 1. Set |integrityPolicy|'s endpoints to |dictionary|['endpoints']. + 1. Return |integrityPolicy|. ### Parse Integrity-Policy headers ### {#parse-integrity-policy-headers-section} To parse Integrity-Policy headers, given a Response |response| @@ -541,11 +542,13 @@ spec:csp3; type:grammar; text:base64-value 1. Let |headers| be |response|'s header list. 1. If |headers| contains a header - whose header name is "`Integrity-Policy`", + whose byte-lowercased header name's isomorphic decode + is "`integrity-policy`", set |container|'s integrity policy be the result of running processing an integrity policy with the corresponding header value. 1. If |headers| contains a header - whose header name is "`Integrity-Policy-Report-Only`", + whose byte-lowercased header name's isomorphic decode + is "`integrity-policy-report-only`", set |container|'s report only integrity policy be the result of running processing an integrity policy with the corresponding header value. @@ -553,28 +556,28 @@ spec:csp3; type:grammar; text:base64-value To determine should request be blocked by integrity policy, given a request |request|, do the following: - 1. Let |policy container| be |request|'s policy container. + 1. Let |policyContainer| be |request|'s policy container. 1. If |request|'s integrity metadata is not the empty string - and |request|'s mode is either "cors" or "same-origin", + and |request|'s mode is either "`cors`" or "`same-origin`", return "Allowed". - 1. Let |policy| be |policy container|'s integrity policy. - 1. Let |report policy| be |policy container|'s report only integrity policy. - 1. If both |policy| and |report policy| are empty integrity policy structs, return "Allowed". + 1. Let |policy| be |policyContainer|'s integrity policy. + 1. Let |reportPolicy| be |policyContainer|'s report only integrity policy. + 1. If both |policy| and |reportPolicy| are empty integrity policy structs, return "Allowed". 1. Let |global| be |request|'s client's global object. - 1. If |global| is not a {{Window}} nor a {{WorkerGlobalScope}}, return "Allowed". + 1. If |global| is not a {{Window}} nor a {{WorkerGlobalScope}}, return "`Allowed`". 1. Let |block| be a boolean, initially false. - 1. Let |report block| be a boolean, initially false. + 1. Let |reportBlock| be a boolean, initially false. 1. If |policy|'s sources contains "`inline`" and |policy|'s blocked destinations contains |request|'s destination, set |block| to true. 1. If |policy|'s sources contains "`inline`" - and |report policy|'s blocked destinations contains + and |reportPolicy|'s blocked destinations contains |request|'s destination, - set |report block| to true. - 1. If |block| or |report block|, report violation with |request|, |block|, |report block|, - |policy| and |report policy|. - 1. If |block|, return "Blocked". Otherwise, return "Allowed". + set |reportBlock| to true. + 1. If |block| is true or |reportBlock| is true, then report violation + with |request|, |block|, |reportBlock|, |policy| and |reportPolicy|. + 1. If |block| is true, then return "`Blocked`"; otherwise "`Allowed`". ### Report violations ### {#report-violations} @@ -590,57 +593,57 @@ spec:csp3; type:grammar; text:base64-value To report violation given a Request |request|, a boolean |block|, - a boolean |report block|, an integrity policy struct |policy|, - and an integrity policy struct |report policy|, do the following: + a boolean |reportBlock|, an integrity policy struct |policy|, + and an integrity policy struct |reportPolicy|, do the following: 1. Assert: |request|'s client is not null. - 1. Let |settings object| be |request|'s client. - 1. Let |global| be |settings object|'s global object. + 1. Let |settingsObject| be |request|'s client. + 1. Let |global| be |settingsObject|'s global object. 1. Assert: |global| is a {{Window}} or a {{WorkerGlobalScope}}. 1. Let |url| be null. 1. If |global| is a {{Window}}, set |url| to |global|'s associated Document's {{Document/URL}}. 1. If |global| is a {{WorkerGlobalScope}}, set |url| to |global|'s URL. - 1. Assert: |url| a URL. - 1. Let |document URL| be the result of strip URL for use in reports on |url|. - 1. Let |blocked URL| be the result of strip URL for use in reports on |request|'s URL. + 1. Assert: |url| is a URL. + 1. Let |documentURL| be the result of strip URL for use in reports on |url|. + 1. Let |blockedURL| be the result of strip URL for use in reports on |request|'s URL. 1. If |block|, for each |endpoint| in |policy|'s endpoints: 1. Let |body| be a new {{IntegrityPolicyViolationReportBody}}, initialized as follows: : {{IntegrityPolicyViolationReportBody/documentURL}} - :: |document URL| + :: |documentURL| : {{IntegrityPolicyViolationReportBody/blockedURL}} - :: |blocked URL| + :: |blockedURL| : {{IntegrityPolicyViolationReportBody/destination}} :: |request|'s destination : {{IntegrityPolicyViolationReportBody/reportOnly}} :: false 2. Generate and queue a report with the following arguments: : context - :: |settings object| + :: |settingsObject| : type - :: "integrity-policy-violation" + :: "`integrity-policy-violation`" : destination :: |endpoint| : data :: |body| - 1. If |report block|, for each |endpoint| in |policy|'s endpoints: - 1. Let |report body| be a new {{IntegrityPolicyViolationReportBody}}, initialized as follows: + 1. If |reportBlock|, for each |endpoint| in |reportPolicy|'s endpoints: + 1. Let |reportBody| be a new {{IntegrityPolicyViolationReportBody}}, initialized as follows: : {{IntegrityPolicyViolationReportBody/documentURL}} - :: |document URL| + :: |documentURL| : {{IntegrityPolicyViolationReportBody/blockedURL}} - :: |blocked URL| + :: |blockedURL| : {{IntegrityPolicyViolationReportBody/destination}} :: |request|'s destination : {{IntegrityPolicyViolationReportBody/reportOnly}} :: true 2. Generate and queue a report with the following arguments: : context - :: |settings object| + :: |settingsObject| : type - :: "integrity-policy-violation" + :: "`integrity-policy-violation`" : destination :: |endpoint| : data - :: |report body| + :: |reportBody| ### Integration ### {#integration} @@ -653,7 +656,7 @@ spec:csp3; type:grammar; text:base64-value parse Integrity-Policy headers with response and result. Expand step 7 of main fetch to call should request be blocked by integrity policy - and return a network error if it returns "blocked" + and return a network error if it returns "`Blocked`". # Proxies # {#proxies} From 562969359ef2919aff5a29533727aca27df3bae7 Mon Sep 17 00:00:00 2001 From: Yoav Weiss Date: Wed, 14 May 2025 22:09:06 +0200 Subject: [PATCH 18/19] More fixups --- index.bs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index 597f48a..dad9412 100644 --- a/index.bs +++ b/index.bs @@ -541,14 +541,10 @@ spec:csp3; type:grammar; text:base64-value and a policy container |container|, do the following: 1. Let |headers| be |response|'s header list. - 1. If |headers| contains a header - whose byte-lowercased header name's isomorphic decode - is "`integrity-policy`", + 1. If |headers| contains ``integrity-policy``, set |container|'s integrity policy be the result of running processing an integrity policy with the corresponding header value. - 1. If |headers| contains a header - whose byte-lowercased header name's isomorphic decode - is "`integrity-policy-report-only`", + 1. If |headers| contains ``integrity-policy-report-only``, set |container|'s report only integrity policy be the result of running processing an integrity policy with the corresponding header value. @@ -606,7 +602,7 @@ spec:csp3; type:grammar; text:base64-value 1. Assert: |url| is a URL. 1. Let |documentURL| be the result of strip URL for use in reports on |url|. 1. Let |blockedURL| be the result of strip URL for use in reports on |request|'s URL. - 1. If |block|, for each |endpoint| in |policy|'s endpoints: + 1. If |block| is true, for each |endpoint| in |policy|'s endpoints: 1. Let |body| be a new {{IntegrityPolicyViolationReportBody}}, initialized as follows: : {{IntegrityPolicyViolationReportBody/documentURL}} :: |documentURL| @@ -625,7 +621,7 @@ spec:csp3; type:grammar; text:base64-value :: |endpoint| : data :: |body| - 1. If |reportBlock|, for each |endpoint| in |reportPolicy|'s endpoints: + 1. If |reportBlock| is true, for each |endpoint| in |reportPolicy|'s endpoints: 1. Let |reportBody| be a new {{IntegrityPolicyViolationReportBody}}, initialized as follows: : {{IntegrityPolicyViolationReportBody/documentURL}} :: |documentURL| From 6b7e05d9232d7aab03afb162378007a72e501eb5 Mon Sep 17 00:00:00 2001 From: Yoav Weiss Date: Fri, 16 May 2025 14:14:10 +0200 Subject: [PATCH 19/19] Link to reporting params --- index.bs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/index.bs b/index.bs index dad9412..f52cecd 100644 --- a/index.bs +++ b/index.bs @@ -613,13 +613,13 @@ spec:csp3; type:grammar; text:base64-value : {{IntegrityPolicyViolationReportBody/reportOnly}} :: false 2. Generate and queue a report with the following arguments: - : context + : context :: |settingsObject| - : type + : type :: "`integrity-policy-violation`" - : destination + : destination :: |endpoint| - : data + : data :: |body| 1. If |reportBlock| is true, for each |endpoint| in |reportPolicy|'s endpoints: 1. Let |reportBody| be a new {{IntegrityPolicyViolationReportBody}}, initialized as follows: @@ -632,13 +632,13 @@ spec:csp3; type:grammar; text:base64-value : {{IntegrityPolicyViolationReportBody/reportOnly}} :: true 2. Generate and queue a report with the following arguments: - : context + : context :: |settingsObject| - : type + : type :: "`integrity-policy-violation`" - : destination + : destination :: |endpoint| - : data + : data :: |reportBody| ### Integration ### {#integration}