Skip to content

Commit 5e43ff0

Browse files
clellandmibrunin
authored andcommitted
[Backport] Security bug 937131
Partial cherry-pick (skipping tests) of patch originally reviewed on https://chromium-review.googlesource.com/c/chromium/src/+/2363169: Change Feature-Policy header semantics This change implements the algorithmic changes for a recent change to the Feature/Permissions policy spec: w3c/webappsec-permissions-policy#378 With this change, the Feature-Policy or Permissions-Policy headers by themselves cannot be used to delegate powerful features to cross-origin iframes; the allow attribute must be used as well. To allow this to still be ergonomic, the default value for the header for powerful features is effectively '*', so that delegation is allowed by the header implicitly. The header can now be used effectively to completely block access to a feature, as any origins not present in the header allowlist cannot be granted the feature through the allow attribute. This also removes some code which previously only existed to track the cases where this change would affect the output of an IsFeatureEnabled call. Several tests will have been modified or rewritten prior to landing this change; this CL depends on the following (though they are all independent, so they are not chained together): - https://crrev.com/c/2424633 - https://crrev.com/c/2424634 - https://crrev.com/c/2424635 - https://crrev.com/c/2424654 - https://crrev.com/c/2424655 - https://crrev.com/c/2424657 - https://crrev.com/c/2425003 - https://crrev.com/c/2425004 (See Patchset 8 for a version with the changes from all of those CLs included.) This CL, while large, can best be understood as the union of the following changes: - Algorithm changes, including the removal of previous "what-if" code and metrics: feature_policy.cc feature_policy.h execution_context.cc - Unit tests to cover those changes: feature_policy_unittest.cc render_frame_host_feature_policy_unittest.cc - Update WPT test expectations to account for the change in behaviour when only the header is used: 3p/b/web_tests/external/wpt/feature-policy/feature-policy-* 3p/b/web_tests/external/wpt/permissions-policy/permissions-policy-* - Update Blink web tests for fullscreen and payment request to validate that both are now working correctly with the new header semantics: 3p/b/web_tests/http/tests/feature-policy/fullscreen* 3p/b/web_tests/http/tests/feature-policy/payment* - Update Blink web tests for the iframe policy JS interface because of new test expectations when features are allowed/disallowed by header: 3p/b/renderer/core/feature_policy/policy_test.cc 3p/b/web_tests/http/tests/feature-policy/policy_iframes.php Bug: 1095641, 937131 Change-Id: Iecbb0950c27a4565998ee5192590d6691a03b4a3 Reviewed-by: Yoav Weiss <[email protected]> Reviewed-by: Charlie Hu <[email protected]> Reviewed-by: Ken Buchanan <[email protected]> Commit-Queue: Ian Clelland <[email protected]> Cr-Commit-Position: refs/heads/master@{#826408} Reviewed-by: Allan Sandfeld Jensen <[email protected]>
1 parent 75d13f3 commit 5e43ff0

File tree

4 files changed

+14
-115
lines changed

4 files changed

+14
-115
lines changed

chromium/third_party/blink/common/feature_policy/feature_policy.cc

Lines changed: 10 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ std::unique_ptr<FeaturePolicy> FeaturePolicy::CreateWithOpenerPolicy(
117117
std::unique_ptr<FeaturePolicy> new_policy = base::WrapUnique(
118118
new FeaturePolicy(origin, GetFeaturePolicyFeatureList()));
119119
new_policy->inherited_policies_ = inherited_policies;
120-
new_policy->proposed_inherited_policies_ = inherited_policies;
121120
return new_policy;
122121
}
123122

@@ -129,12 +128,6 @@ bool FeaturePolicy::IsFeatureEnabled(
129128
bool FeaturePolicy::IsFeatureEnabledForOrigin(
130129
mojom::FeaturePolicyFeature feature,
131130
const url::Origin& origin) const {
132-
return GetFeatureValueForOrigin(feature, origin);
133-
}
134-
135-
bool FeaturePolicy::GetFeatureValueForOrigin(
136-
mojom::FeaturePolicyFeature feature,
137-
const url::Origin& origin) const {
138131
DCHECK(base::Contains(feature_list_, feature));
139132
DCHECK(base::Contains(inherited_policies_, feature));
140133

@@ -149,27 +142,22 @@ bool FeaturePolicy::GetFeatureValueForOrigin(
149142
if (default_policy == FeaturePolicyFeatureDefault::EnableForSelf &&
150143
!origin_.IsSameOriginWith(origin))
151144
return false;
145+
152146
return inherited_value;
153147
}
154148

155-
// Temporary code to support metrics: (https://crbug.com/937131)
156-
// This method implements a proposed algorithm change to feature policy in which
157-
// the default allowlist for a feature if not specified in the header, is always
158-
// '*', but where the header allowlist *must* allow the nested frame origin in
159-
// order to delegate use of the feature to that frame.
160-
bool FeaturePolicy::GetProposedFeatureValueForOrigin(
149+
bool FeaturePolicy::GetFeatureValueForOrigin(
161150
mojom::FeaturePolicyFeature feature,
162151
const url::Origin& origin) const {
163152
DCHECK(base::Contains(feature_list_, feature));
164-
DCHECK(base::Contains(proposed_inherited_policies_, feature));
153+
DCHECK(base::Contains(inherited_policies_, feature));
165154

166-
auto inherited_value = proposed_inherited_policies_.at(feature);
155+
auto inherited_value = inherited_policies_.at(feature);
167156
auto allowlist = allowlists_.find(feature);
168157
if (allowlist != allowlists_.end()) {
169158
return inherited_value && allowlist->second->Contains(origin);
170159
}
171160

172-
// If no allowlist is specified, return default feature value.
173161
return inherited_value;
174162
}
175163

@@ -236,53 +224,16 @@ std::unique_ptr<FeaturePolicy> FeaturePolicy::CreateFromParentPolicy(
236224
base::WrapUnique(new FeaturePolicy(origin, features));
237225
for (const auto& feature : features) {
238226
new_policy->inherited_policies_[feature.first] =
239-
new_policy->GetInheritedValueForFeature(parent_policy, feature,
240-
container_policy);
241-
new_policy->proposed_inherited_policies_[feature.first] =
242-
new_policy->GetProposedInheritedValueForFeature(parent_policy, feature,
243-
container_policy);
227+
new_policy->InheritedValueForFeature(parent_policy, feature,
228+
container_policy);
244229
}
245230
return new_policy;
246231
}
247232

248-
// Implements Feature Policy 9.8: Define an inherited policy for feature in
249-
// document and 9.9: Define an inherited policy for feature in container at
250-
// origin.
251-
bool FeaturePolicy::GetInheritedValueForFeature(
252-
const FeaturePolicy* parent_policy,
253-
std::pair<mojom::FeaturePolicyFeature, FeaturePolicyFeatureDefault> feature,
254-
const ParsedFeaturePolicy& container_policy) const {
255-
// 9.8 3: Otherwise [If context is not a nested browsing context,] return
256-
// "Enabled".
257-
if (!parent_policy)
258-
return true;
259-
260-
for (const auto& decl : container_policy) {
261-
if (decl.feature == feature.first) {
262-
// 9.9 3.1: If the allowlist for feature in container policy does not
263-
// match origin, return "Disabled".
264-
if (!AllowlistFromDeclaration(decl, feature_list_)->Contains(origin_))
265-
return false;
266-
267-
// 9.9 3.2: If feature is enabled in parent for parent’s origin, return
268-
// "Enabled".
269-
if (parent_policy->GetFeatureValueForOrigin(feature.first,
270-
parent_policy->origin_))
271-
return true;
272-
}
273-
}
274-
275-
// 9.9 4: If feature is enabled in parent for parent’s origin, return
276-
// "Enabled".
277-
// 9.9 5: Otherwise return "Disabled".
278-
return parent_policy->GetFeatureValueForOrigin(feature.first, origin_);
279-
}
280-
281-
// Temporary code to support metrics (https://crbug.com/937131)
282233
// Implements Permissions Policy 9.7: Define an inherited policy for feature in
283234
// browsing context and 9.8: Define an inherited policy for feature in container
284235
// at origin.
285-
bool FeaturePolicy::GetProposedInheritedValueForFeature(
236+
bool FeaturePolicy::InheritedValueForFeature(
286237
const FeaturePolicy* parent_policy,
287238
std::pair<mojom::FeaturePolicyFeature, FeaturePolicyFeatureDefault> feature,
288239
const ParsedFeaturePolicy& container_policy) const {
@@ -293,14 +244,14 @@ bool FeaturePolicy::GetProposedInheritedValueForFeature(
293244

294245
// 9.8 2: If policy’s inherited policy for feature is "Disabled", return
295246
// "Disabled".
296-
if (!parent_policy->GetProposedFeatureValueForOrigin(feature.first,
297-
parent_policy->origin_))
247+
if (!parent_policy->GetFeatureValueForOrigin(feature.first,
248+
parent_policy->origin_))
298249
return false;
299250

300251
// 9.8 3: If feature is present in policy’s declared policy, and the allowlist
301252
// for feature in policy’s declared policy does not match origin, then return
302253
// "Disabled".
303-
if (!parent_policy->GetProposedFeatureValueForOrigin(feature.first, origin_))
254+
if (!parent_policy->GetFeatureValueForOrigin(feature.first, origin_))
304255
return false;
305256

306257
for (const auto& decl : container_policy) {

chromium/third_party/blink/public/common/feature_policy/feature_policy.h

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -180,13 +180,6 @@ class BLINK_COMMON_EXPORT FeaturePolicy {
180180
bool IsFeatureEnabledForOrigin(mojom::FeaturePolicyFeature feature,
181181
const url::Origin& origin) const;
182182

183-
// Returns the value of the given feature on the given origin.
184-
bool GetFeatureValueForOrigin(mojom::FeaturePolicyFeature feature,
185-
const url::Origin& origin) const;
186-
187-
bool GetProposedFeatureValueForOrigin(mojom::FeaturePolicyFeature feature,
188-
const url::Origin& origin) const;
189-
190183
// Returns the allowlist of a given feature by this policy.
191184
const Allowlist GetAllowlistForFeature(
192185
mojom::FeaturePolicyFeature feature) const;
@@ -218,17 +211,15 @@ class BLINK_COMMON_EXPORT FeaturePolicy {
218211
const url::Origin& origin,
219212
const FeaturePolicyFeatureList& features);
220213

221-
bool GetInheritedValueForFeature(
214+
bool InheritedValueForFeature(
222215
const FeaturePolicy* parent_policy,
223216
std::pair<mojom::FeaturePolicyFeature, FeaturePolicyFeatureDefault>
224217
feature,
225218
const ParsedFeaturePolicy& container_policy) const;
226219

227-
bool GetProposedInheritedValueForFeature(
228-
const FeaturePolicy* parent_policy,
229-
std::pair<mojom::FeaturePolicyFeature, FeaturePolicyFeatureDefault>
230-
feature,
231-
const ParsedFeaturePolicy& container_policy) const;
220+
// Returns the value of the given feature on the given origin.
221+
bool GetFeatureValueForOrigin(mojom::FeaturePolicyFeature feature,
222+
const url::Origin& origin) const;
232223

233224
// The origin of the document with which this policy is associated.
234225
url::Origin origin_;
@@ -241,11 +232,6 @@ class BLINK_COMMON_EXPORT FeaturePolicy {
241232
// parent frame.
242233
FeaturePolicyFeatureState inherited_policies_;
243234

244-
// Temporary member to support metrics. These are the values which would be
245-
// stored in |inherited_policies_| under the proposal in
246-
// https://crbug.com/937131.
247-
FeaturePolicyFeatureState proposed_inherited_policies_;
248-
249235
const FeaturePolicyFeatureList& feature_list_;
250236

251237
DISALLOW_COPY_AND_ASSIGN(FeaturePolicy);

chromium/third_party/blink/renderer/core/execution_context/execution_context.cc

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -412,20 +412,6 @@ bool ExecutionContext::FeatureEnabled(OriginTrialFeature feature) const {
412412
return origin_trial_context_->IsFeatureEnabled(feature);
413413
}
414414

415-
void ExecutionContext::FeaturePolicyPotentialBehaviourChangeObserved(
416-
mojom::blink::FeaturePolicyFeature feature) const {
417-
size_t feature_index = static_cast<size_t>(feature);
418-
if (feature_policy_behaviour_change_counted_.size() == 0) {
419-
feature_policy_behaviour_change_counted_.resize(
420-
static_cast<size_t>(mojom::blink::FeaturePolicyFeature::kMaxValue) + 1);
421-
} else if (feature_policy_behaviour_change_counted_[feature_index]) {
422-
return;
423-
}
424-
feature_policy_behaviour_change_counted_[feature_index] = true;
425-
UMA_HISTOGRAM_ENUMERATION(
426-
"Blink.UseCounter.FeaturePolicy.ProposalWouldChangeBehaviour", feature);
427-
}
428-
429415
bool ExecutionContext::IsFeatureEnabled(
430416
mojom::blink::FeaturePolicyFeature feature,
431417
ReportOptions report_on_failure,
@@ -440,20 +426,6 @@ bool ExecutionContext::IsFeatureEnabled(
440426
bool should_report;
441427
bool enabled = security_context_.IsFeatureEnabled(feature, &should_report);
442428

443-
if (enabled) {
444-
// Report if the proposed header semantics change would have affected the
445-
// outcome. (https://crbug.com/937131)
446-
const FeaturePolicy* policy = security_context_.GetFeaturePolicy();
447-
url::Origin origin = GetSecurityOrigin()->ToUrlOrigin();
448-
if (!policy->GetProposedFeatureValueForOrigin(feature, origin)) {
449-
// Count that there was a change in this page load.
450-
const_cast<ExecutionContext*>(this)->CountUse(
451-
WebFeature::kFeaturePolicyProposalWouldChangeBehaviour);
452-
// Record the specific feature whose behaviour was changed.
453-
FeaturePolicyPotentialBehaviourChangeObserved(feature);
454-
}
455-
}
456-
457429
if (should_report && report_on_failure == ReportOptions::kReportOnFailure) {
458430
mojom::blink::PolicyDisposition disposition =
459431
enabled ? mojom::blink::PolicyDisposition::kReport

chromium/third_party/blink/renderer/core/execution_context/execution_context.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -422,11 +422,6 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
422422
virtual void AddConsoleMessageImpl(ConsoleMessage*,
423423
bool discard_duplicates) = 0;
424424

425-
// Temporary method to record when the result of calling IsFeatureEnabled
426-
// would change under the proposal in https://crbug.com/937131.
427-
void FeaturePolicyPotentialBehaviourChangeObserved(
428-
mojom::blink::FeaturePolicyFeature feature) const;
429-
430425
v8::Isolate* const isolate_;
431426

432427
SecurityContext security_context_;
@@ -470,11 +465,6 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
470465
network::mojom::blink::IPAddressSpace address_space_;
471466

472467
Member<OriginTrialContext> origin_trial_context_;
473-
474-
// Tracks which feature policy features have been logged in this execution
475-
// context as to the FeaturePolicyProposalWouldChangeBehaviour
476-
// histogram, in order not to overcount.
477-
mutable Vector<bool> feature_policy_behaviour_change_counted_;
478468
};
479469

480470
} // namespace blink

0 commit comments

Comments
 (0)