Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(116)

Side by Side Diff: content/common/content_security_policy/csp_context_unittest.cc

Issue 2910573002: Implement upgrade-insecure-requests in browser for frame requests (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <set> 5 #include <set>
6 6
7 #include "content/common/content_security_policy/csp_context.h" 7 #include "content/common/content_security_policy/csp_context.h"
8 #include "content/common/content_security_policy_header.h" 8 #include "content/common/content_security_policy_header.h"
9 #include "content/common/navigation_params.h" 9 #include "content/common/navigation_params.h"
10 #include "testing/gtest/include/gtest/gtest.h" 10 #include "testing/gtest/include/gtest/gtest.h"
11 11
12 namespace content { 12 namespace content {
13 13
14 namespace { 14 namespace {
15 15
16 class CSPContextTest : public CSPContext { 16 class CSPContextTest : public CSPContext {
17 public: 17 public:
18 const std::vector<CSPViolationParams>& violations() { return violations_; } 18 const std::vector<CSPViolationParams>& violations() { return violations_; }
19 19
20 void AddSchemeToBypassCSP(const std::string& scheme) { 20 void AddSchemeToBypassCSP(const std::string& scheme) {
21 scheme_to_bypass_.insert(scheme); 21 scheme_to_bypass_.insert(scheme);
22 } 22 }
23 23
24 bool SchemeShouldBypassCSP(const base::StringPiece& scheme) override { 24 bool SchemeShouldBypassCSP(const base::StringPiece& scheme) override {
25 return scheme_to_bypass_.count(scheme.as_string()); 25 return scheme_to_bypass_.count(scheme.as_string());
26 } 26 }
27 27
28 void ClearViolations() { violations_.clear(); }
29
28 void set_sanitize_data_for_use_in_csp_violation(bool value) { 30 void set_sanitize_data_for_use_in_csp_violation(bool value) {
29 sanitize_data_for_use_in_csp_violation_ = value; 31 sanitize_data_for_use_in_csp_violation_ = value;
30 } 32 }
31 33
32 void SanitizeDataForUseInCspViolation( 34 void SanitizeDataForUseInCspViolation(
33 bool is_redirect, 35 bool is_redirect,
34 CSPDirective::Name directive, 36 CSPDirective::Name directive,
35 GURL* blocked_url, 37 GURL* blocked_url,
36 SourceLocation* source_location) const override { 38 SourceLocation* source_location) const override {
37 if (!sanitize_data_for_use_in_csp_violation_) 39 if (!sanitize_data_for_use_in_csp_violation_)
(...skipping 25 matching lines...) Expand all
63 } 65 }
64 66
65 } // namespace 67 } // namespace
66 68
67 TEST(CSPContextTest, SchemeShouldBypassCSP) { 69 TEST(CSPContextTest, SchemeShouldBypassCSP) {
68 CSPSource source("", "example.com", false, url::PORT_UNSPECIFIED, false, ""); 70 CSPSource source("", "example.com", false, url::PORT_UNSPECIFIED, false, "");
69 CSPContextTest context; 71 CSPContextTest context;
70 context.AddContentSecurityPolicy( 72 context.AddContentSecurityPolicy(
71 BuildPolicy(CSPDirective::DefaultSrc, {source})); 73 BuildPolicy(CSPDirective::DefaultSrc, {source}));
72 74
73 EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, 75 EXPECT_FALSE(context.IsAllowedByCsp(
74 GURL("data:text/html,<html></html>"), 76 CSPDirective::FrameSrc, GURL("data:text/html,<html></html>"), false,
75 false, SourceLocation())); 77 SourceLocation(), CSPContext::CHECK_ALL_CSP));
76 78
77 context.AddSchemeToBypassCSP("data"); 79 context.AddSchemeToBypassCSP("data");
78 80
79 EXPECT_TRUE(context.IsAllowedByCsp(CSPDirective::FrameSrc, 81 EXPECT_TRUE(context.IsAllowedByCsp(
80 GURL("data:text/html,<html></html>"), 82 CSPDirective::FrameSrc, GURL("data:text/html,<html></html>"), false,
81 false, SourceLocation())); 83 SourceLocation(), CSPContext::CHECK_ALL_CSP));
82 } 84 }
83 85
84 TEST(CSPContextTest, MultiplePolicies) { 86 TEST(CSPContextTest, MultiplePolicies) {
85 CSPContextTest context; 87 CSPContextTest context;
86 context.SetSelf(url::Origin(GURL("http://example.com"))); 88 context.SetSelf(url::Origin(GURL("http://example.com")));
87 89
88 CSPSource source_a("", "a.com", false, url::PORT_UNSPECIFIED, false, ""); 90 CSPSource source_a("", "a.com", false, url::PORT_UNSPECIFIED, false, "");
89 CSPSource source_b("", "b.com", false, url::PORT_UNSPECIFIED, false, ""); 91 CSPSource source_b("", "b.com", false, url::PORT_UNSPECIFIED, false, "");
90 CSPSource source_c("", "c.com", false, url::PORT_UNSPECIFIED, false, ""); 92 CSPSource source_c("", "c.com", false, url::PORT_UNSPECIFIED, false, "");
91 93
92 context.AddContentSecurityPolicy( 94 context.AddContentSecurityPolicy(
93 BuildPolicy(CSPDirective::FrameSrc, {source_a, source_b})); 95 BuildPolicy(CSPDirective::FrameSrc, {source_a, source_b}));
94 context.AddContentSecurityPolicy( 96 context.AddContentSecurityPolicy(
95 BuildPolicy(CSPDirective::FrameSrc, {source_a, source_c})); 97 BuildPolicy(CSPDirective::FrameSrc, {source_a, source_c}));
96 98
97 EXPECT_TRUE(context.IsAllowedByCsp( 99 EXPECT_TRUE(context.IsAllowedByCsp(
98 CSPDirective::FrameSrc, GURL("http://a.com"), false, SourceLocation())); 100 CSPDirective::FrameSrc, GURL("http://a.com"), false, SourceLocation(),
101 CSPContext::CHECK_ALL_CSP));
99 EXPECT_FALSE(context.IsAllowedByCsp( 102 EXPECT_FALSE(context.IsAllowedByCsp(
100 CSPDirective::FrameSrc, GURL("http://b.com"), false, SourceLocation())); 103 CSPDirective::FrameSrc, GURL("http://b.com"), false, SourceLocation(),
104 CSPContext::CHECK_ALL_CSP));
101 EXPECT_FALSE(context.IsAllowedByCsp( 105 EXPECT_FALSE(context.IsAllowedByCsp(
102 CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation())); 106 CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation(),
107 CSPContext::CHECK_ALL_CSP));
103 EXPECT_FALSE(context.IsAllowedByCsp( 108 EXPECT_FALSE(context.IsAllowedByCsp(
104 CSPDirective::FrameSrc, GURL("http://d.com"), false, SourceLocation())); 109 CSPDirective::FrameSrc, GURL("http://d.com"), false, SourceLocation(),
110 CSPContext::CHECK_ALL_CSP));
105 } 111 }
106 112
107 TEST(CSPContextTest, SanitizeDataForUseInCspViolation) { 113 TEST(CSPContextTest, SanitizeDataForUseInCspViolation) {
108 CSPContextTest context; 114 CSPContextTest context;
109 context.SetSelf(url::Origin(GURL("http://a.com"))); 115 context.SetSelf(url::Origin(GURL("http://a.com")));
110 116
111 // Content-Security-Policy: frame-src "a.com/iframe" 117 // Content-Security-Policy: frame-src "a.com/iframe"
112 context.AddContentSecurityPolicy( 118 context.AddContentSecurityPolicy(
113 BuildPolicy(CSPDirective::FrameSrc, 119 BuildPolicy(CSPDirective::FrameSrc,
114 {CSPSource("", "a.com", false, url::PORT_UNSPECIFIED, false, 120 {CSPSource("", "a.com", false, url::PORT_UNSPECIFIED, false,
115 "/iframe")})); 121 "/iframe")}));
116 122
117 GURL blocked_url("http://a.com/login?password=1234"); 123 GURL blocked_url("http://a.com/login?password=1234");
118 SourceLocation source_location("http://a.com/login", 10u, 20u); 124 SourceLocation source_location("http://a.com/login", 10u, 20u);
119 125
120 // When the |blocked_url| and |source_location| aren't sensitive information. 126 // When the |blocked_url| and |source_location| aren't sensitive information.
121 { 127 {
122 EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url, 128 EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url,
123 false, source_location)); 129 false, source_location,
130 CSPContext::CHECK_ALL_CSP));
124 ASSERT_EQ(1u, context.violations().size()); 131 ASSERT_EQ(1u, context.violations().size());
125 EXPECT_EQ(context.violations()[0].blocked_url, blocked_url); 132 EXPECT_EQ(context.violations()[0].blocked_url, blocked_url);
126 EXPECT_EQ(context.violations()[0].source_location.url, 133 EXPECT_EQ(context.violations()[0].source_location.url,
127 "http://a.com/login"); 134 "http://a.com/login");
128 EXPECT_EQ(context.violations()[0].source_location.line_number, 10u); 135 EXPECT_EQ(context.violations()[0].source_location.line_number, 10u);
129 EXPECT_EQ(context.violations()[0].source_location.column_number, 20u); 136 EXPECT_EQ(context.violations()[0].source_location.column_number, 20u);
130 EXPECT_EQ(context.violations()[0].console_message, 137 EXPECT_EQ(context.violations()[0].console_message,
131 "Refused to frame 'http://a.com/login?password=1234' because it " 138 "Refused to frame 'http://a.com/login?password=1234' because it "
132 "violates the following Content Security Policy directive: " 139 "violates the following Content Security Policy directive: "
133 "\"frame-src a.com/iframe\".\n"); 140 "\"frame-src a.com/iframe\".\n");
134 } 141 }
135 142
136 context.set_sanitize_data_for_use_in_csp_violation(true); 143 context.set_sanitize_data_for_use_in_csp_violation(true);
137 144
138 // When the |blocked_url| and |source_location| are sensitive information. 145 // When the |blocked_url| and |source_location| are sensitive information.
139 { 146 {
140 EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url, 147 EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url,
141 false, source_location)); 148 false, source_location,
149 CSPContext::CHECK_ALL_CSP));
142 ASSERT_EQ(2u, context.violations().size()); 150 ASSERT_EQ(2u, context.violations().size());
143 EXPECT_EQ(context.violations()[1].blocked_url, blocked_url.GetOrigin()); 151 EXPECT_EQ(context.violations()[1].blocked_url, blocked_url.GetOrigin());
144 EXPECT_EQ(context.violations()[1].source_location.url, "http://a.com/"); 152 EXPECT_EQ(context.violations()[1].source_location.url, "http://a.com/");
145 EXPECT_EQ(context.violations()[1].source_location.line_number, 0u); 153 EXPECT_EQ(context.violations()[1].source_location.line_number, 0u);
146 EXPECT_EQ(context.violations()[1].source_location.column_number, 0u); 154 EXPECT_EQ(context.violations()[1].source_location.column_number, 0u);
147 EXPECT_EQ(context.violations()[1].console_message, 155 EXPECT_EQ(context.violations()[1].console_message,
148 "Refused to frame 'http://a.com/' because it violates the " 156 "Refused to frame 'http://a.com/' because it violates the "
149 "following Content Security Policy directive: \"frame-src " 157 "following Content Security Policy directive: \"frame-src "
150 "a.com/iframe\".\n"); 158 "a.com/iframe\".\n");
151 } 159 }
152 } 160 }
153 161
154 // When several policies are infringed, all of them must be reported. 162 // When several policies are infringed, all of them must be reported.
155 TEST(CSPContextTest, MultipleInfringement) { 163 TEST(CSPContextTest, MultipleInfringement) {
156 CSPContextTest context; 164 CSPContextTest context;
157 context.SetSelf(url::Origin(GURL("http://example.com"))); 165 context.SetSelf(url::Origin(GURL("http://example.com")));
158 166
159 CSPSource source_a("", "a.com", false, url::PORT_UNSPECIFIED, false, ""); 167 CSPSource source_a("", "a.com", false, url::PORT_UNSPECIFIED, false, "");
160 CSPSource source_b("", "b.com", false, url::PORT_UNSPECIFIED, false, ""); 168 CSPSource source_b("", "b.com", false, url::PORT_UNSPECIFIED, false, "");
161 CSPSource source_c("", "c.com", false, url::PORT_UNSPECIFIED, false, ""); 169 CSPSource source_c("", "c.com", false, url::PORT_UNSPECIFIED, false, "");
162 170
163 context.AddContentSecurityPolicy( 171 context.AddContentSecurityPolicy(
164 BuildPolicy(CSPDirective::FrameSrc, {source_a})); 172 BuildPolicy(CSPDirective::FrameSrc, {source_a}));
165 context.AddContentSecurityPolicy( 173 context.AddContentSecurityPolicy(
166 BuildPolicy(CSPDirective::FrameSrc, {source_b})); 174 BuildPolicy(CSPDirective::FrameSrc, {source_b}));
167 context.AddContentSecurityPolicy( 175 context.AddContentSecurityPolicy(
168 BuildPolicy(CSPDirective::FrameSrc, {source_c})); 176 BuildPolicy(CSPDirective::FrameSrc, {source_c}));
169 177
170 EXPECT_FALSE(context.IsAllowedByCsp( 178 EXPECT_FALSE(context.IsAllowedByCsp(
171 CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation())); 179 CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation(),
180 CSPContext::CHECK_ALL_CSP));
172 ASSERT_EQ(2u, context.violations().size()); 181 ASSERT_EQ(2u, context.violations().size());
173 const char console_message_a[] = 182 const char console_message_a[] =
174 "Refused to frame 'http://c.com/' because it violates the following " 183 "Refused to frame 'http://c.com/' because it violates the following "
175 "Content Security Policy directive: \"frame-src a.com\".\n"; 184 "Content Security Policy directive: \"frame-src a.com\".\n";
176 const char console_message_b[] = 185 const char console_message_b[] =
177 "Refused to frame 'http://c.com/' because it violates the following " 186 "Refused to frame 'http://c.com/' because it violates the following "
178 "Content Security Policy directive: \"frame-src b.com\".\n"; 187 "Content Security Policy directive: \"frame-src b.com\".\n";
179 EXPECT_EQ(console_message_a, context.violations()[0].console_message); 188 EXPECT_EQ(console_message_a, context.violations()[0].console_message);
180 EXPECT_EQ(console_message_b, context.violations()[1].console_message); 189 EXPECT_EQ(console_message_b, context.violations()[1].console_message);
181 } 190 }
182 191
192 // Tests that the CheckCSPDisposition parameter is obeyed.
193 TEST(CSPContextTest, CheckCSPDisposition) {
194 CSPSource source("", "example.com", false, url::PORT_UNSPECIFIED, false, "");
195 CSPContextTest context;
196
197 // Add an enforced policy.
198 context.AddContentSecurityPolicy(
199 BuildPolicy(CSPDirective::FrameSrc, {source}));
200
201 // Add a report-only policy.
202 ContentSecurityPolicy report_only =
203 BuildPolicy(CSPDirective::DefaultSrc, {source});
204 report_only.header.type = blink::kWebContentSecurityPolicyTypeReport;
205 context.AddContentSecurityPolicy(report_only);
206
207 // With CHECK_ALL_CSP, both policies should be checked and violations should
208 // be reported.
209 EXPECT_FALSE(context.IsAllowedByCsp(
210 CSPDirective::FrameSrc, GURL("https://not-example.com"), false,
211 SourceLocation(), CSPContext::CHECK_ALL_CSP));
212 ASSERT_EQ(2u, context.violations().size());
213 const char console_message_a[] =
214 "Refused to frame 'https://not-example.com/' because it violates the "
215 "following "
216 "Content Security Policy directive: \"frame-src example.com\".\n";
217 const char console_message_b[] =
218 "[Report Only] Refused to frame 'https://not-example.com/' because it "
219 "violates the following "
220 "Content Security Policy directive: \"default-src example.com\". Note "
221 "that 'frame-src' was not explicitly set, so 'default-src' is used as a "
222 "fallback.\n";
223 // Both console messages must appear in the reported violations.
224 EXPECT_TRUE((console_message_a == context.violations()[0].console_message &&
225 console_message_b == context.violations()[1].console_message) ||
226 (console_message_a == context.violations()[1].console_message &&
227 console_message_b == context.violations()[0].console_message));
228
229 // With CHECK_REPORT_ONLY_CSP, the request should be allowed but reported.
230 context.ClearViolations();
231 EXPECT_TRUE(context.IsAllowedByCsp(
232 CSPDirective::FrameSrc, GURL("https://not-example.com"), false,
233 SourceLocation(), CSPContext::CHECK_REPORT_ONLY_CSP));
234 ASSERT_EQ(1u, context.violations().size());
235 EXPECT_EQ(console_message_b, context.violations()[0].console_message);
236
237 // With CHECK_ENFORCED_CSP, the request should be blocked and only the
238 // enforced policy violation should be reported.
239 context.ClearViolations();
240 EXPECT_FALSE(context.IsAllowedByCsp(
241 CSPDirective::FrameSrc, GURL("https://not-example.com"), false,
242 SourceLocation(), CSPContext::CHECK_ENFORCED_CSP));
243 ASSERT_EQ(1u, context.violations().size());
244 EXPECT_EQ(console_message_a, context.violations()[0].console_message);
245 }
246
247 // Tests HTTP subresources and form submissions have their URLs upgraded when
248 // upgrade-insecure-requests is present.
249 TEST(CSPContextTest, ShouldModifyRequestUrlForCsp) {
250 CSPContextTest context;
251 context.AddContentSecurityPolicy(BuildPolicy(
252 CSPDirective::UpgradeInsecureRequests, std::vector<CSPSource>()));
253 GURL new_url;
254 // An HTTP subresource or form submission should be upgraded.
255 EXPECT_TRUE(context.ShouldModifyRequestUrlForCsp(GURL("http://example.com"),
256 true, &new_url));
257 EXPECT_EQ(GURL("https://example.com"), new_url);
258 EXPECT_TRUE(context.ShouldModifyRequestUrlForCsp(
259 GURL("http://example.com:80"), true, &new_url));
260 EXPECT_EQ(GURL("https://example.com:443"), new_url);
261 // Non-standard ports should not be modified.
262 EXPECT_TRUE(context.ShouldModifyRequestUrlForCsp(
263 GURL("http://example-weird-port.com:8088"), true, &new_url));
264 EXPECT_EQ(GURL("https://example-weird-port.com:8088"), new_url);
265
266 // Non-HTTP URLs don't need to be modified.
267 EXPECT_FALSE(context.ShouldModifyRequestUrlForCsp(GURL("https://example.com"),
268 true, &new_url));
269 EXPECT_FALSE(context.ShouldModifyRequestUrlForCsp(
270 GURL("data:text/html,<html></html>"), true, &new_url));
271 // Nor do main-frame navigation requests.
272 EXPECT_FALSE(context.ShouldModifyRequestUrlForCsp(GURL("http://example.com"),
273 false, &new_url));
274 }
275
183 } // namespace content 276 } // namespace content
OLDNEW
« no previous file with comments | « content/common/content_security_policy/csp_context.cc ('k') | content/common/content_security_policy/csp_directive.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698