OLD | NEW |
---|---|
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 "content/common/content_security_policy/csp_context.h" | 5 #include "content/common/content_security_policy/csp_context.h" |
6 #include "content/common/content_security_policy_header.h" | 6 #include "content/common/content_security_policy_header.h" |
7 #include "content/common/navigation_params.h" | 7 #include "content/common/navigation_params.h" |
8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
9 | 9 |
10 namespace content { | 10 namespace content { |
11 | 11 |
12 namespace { | 12 namespace { |
13 | 13 |
14 class CSPContextTest : public CSPContext { | 14 class CSPContextTest : public CSPContext { |
15 public: | 15 public: |
16 const std::string& LastConsoleMessage() { return console_message_; } | 16 const CSPViolationParams& LastViolation() { return last_violation_; } |
17 | 17 |
18 void AddSchemeToBypassCSP(const std::string& scheme) { | 18 void AddSchemeToBypassCSP(const std::string& scheme) { |
19 scheme_to_bypass_.push_back(scheme); | 19 scheme_to_bypass_.push_back(scheme); |
20 } | 20 } |
21 | 21 |
22 bool SchemeShouldBypassCSP(const base::StringPiece& scheme) override { | 22 bool SchemeShouldBypassCSP(const base::StringPiece& scheme) override { |
23 return std::find(scheme_to_bypass_.begin(), scheme_to_bypass_.end(), | 23 return std::find(scheme_to_bypass_.begin(), scheme_to_bypass_.end(), |
24 scheme) != scheme_to_bypass_.end(); | 24 scheme) != scheme_to_bypass_.end(); |
25 } | 25 } |
26 | 26 |
27 void AddOriginUnsafeToUseInCspViolation(const url::Origin& origin) { | |
28 origins_unsafe_to_use_in_csp_violation_.push_back(origin); | |
29 } | |
30 | |
31 bool IsOriginSafeToUseInCspViolation( | |
32 const url::Origin& origin) const override { | |
33 return std::find(origins_unsafe_to_use_in_csp_violation_.begin(), | |
34 origins_unsafe_to_use_in_csp_violation_.end(), | |
35 origin) == origins_unsafe_to_use_in_csp_violation_.end(); | |
36 } | |
37 | |
27 private: | 38 private: |
28 void ReportContentSecurityPolicyViolation( | 39 void ReportContentSecurityPolicyViolation( |
29 const CSPViolationParams& violation_params) override { | 40 const CSPViolationParams& violation_params) override { |
30 console_message_ = violation_params.console_message; | 41 last_violation_ = violation_params; |
31 } | 42 } |
32 std::string console_message_; | 43 CSPViolationParams last_violation_; |
44 SourceLocation source_location_; | |
33 std::vector<std::string> scheme_to_bypass_; | 45 std::vector<std::string> scheme_to_bypass_; |
46 std::vector<url::Origin> origins_unsafe_to_use_in_csp_violation_; | |
alexmos
2017/05/10 22:33:08
Why not std::set? That'll also let you use origin
arthursonzogni
2017/05/11 13:06:23
You are absolutely right.
| |
34 }; | 47 }; |
35 | 48 |
36 // Build a new policy made of only one directive and no report endpoints. | 49 // Build a new policy made of only one directive and no report endpoints. |
37 ContentSecurityPolicy BuildPolicy(CSPDirective::Name directive_name, | 50 ContentSecurityPolicy BuildPolicy(CSPDirective::Name directive_name, |
38 std::vector<CSPSource> sources) { | 51 std::vector<CSPSource> sources) { |
39 return ContentSecurityPolicy( | 52 return ContentSecurityPolicy( |
40 ContentSecurityPolicyHeader(std::string(), // header | 53 ContentSecurityPolicyHeader(std::string(), // header |
41 blink::kWebContentSecurityPolicyTypeEnforce, | 54 blink::kWebContentSecurityPolicyTypeEnforce, |
42 blink::kWebContentSecurityPolicySourceHTTP), | 55 blink::kWebContentSecurityPolicySourceHTTP), |
43 {CSPDirective(directive_name, CSPSourceList(false, false, sources))}, | 56 {CSPDirective(directive_name, CSPSourceList(false, false, sources))}, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
79 EXPECT_TRUE(context.IsAllowedByCsp( | 92 EXPECT_TRUE(context.IsAllowedByCsp( |
80 CSPDirective::FrameSrc, GURL("http://a.com"), false, SourceLocation())); | 93 CSPDirective::FrameSrc, GURL("http://a.com"), false, SourceLocation())); |
81 EXPECT_FALSE(context.IsAllowedByCsp( | 94 EXPECT_FALSE(context.IsAllowedByCsp( |
82 CSPDirective::FrameSrc, GURL("http://b.com"), false, SourceLocation())); | 95 CSPDirective::FrameSrc, GURL("http://b.com"), false, SourceLocation())); |
83 EXPECT_FALSE(context.IsAllowedByCsp( | 96 EXPECT_FALSE(context.IsAllowedByCsp( |
84 CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation())); | 97 CSPDirective::FrameSrc, GURL("http://c.com"), false, SourceLocation())); |
85 EXPECT_FALSE(context.IsAllowedByCsp( | 98 EXPECT_FALSE(context.IsAllowedByCsp( |
86 CSPDirective::FrameSrc, GURL("http://d.com"), false, SourceLocation())); | 99 CSPDirective::FrameSrc, GURL("http://d.com"), false, SourceLocation())); |
87 } | 100 } |
88 | 101 |
102 TEST(CSPContextTest, IsOriginSafeToUseInCspViolation) { | |
103 CSPContextTest context; | |
104 context.SetSelf(url::Origin(GURL("http://a.com"))); | |
105 | |
106 // Content-Security-Policy: frame-src "a.com/iframe" | |
107 context.AddContentSecurityPolicy( | |
108 BuildPolicy(CSPDirective::FrameSrc, | |
109 {CSPSource("", "a.com", false, url::PORT_UNSPECIFIED, false, | |
110 "/iframe")})); | |
111 | |
112 GURL blocked_url("http://a.com/login?password=1234"); | |
113 SourceLocation source_location("http://a.com/login", 10u, 20u); | |
114 | |
115 // When the |blocked_url| and |source_location| aren't sensitive information. | |
116 { | |
117 EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url, | |
118 false, source_location)); | |
119 EXPECT_EQ(context.LastViolation().blocked_url, blocked_url); | |
120 EXPECT_EQ(context.LastViolation().source_location.url, | |
121 "http://a.com/login"); | |
122 EXPECT_EQ(context.LastViolation().source_location.line_number, 10u); | |
123 EXPECT_EQ(context.LastViolation().source_location.column_number, 20u); | |
124 EXPECT_EQ(context.LastViolation().console_message, | |
125 "Refused to frame 'http://a.com/login?password=1234' because it " | |
126 "violates the following Content Security Policy directive: " | |
127 "\"frame-src a.com/iframe\".\n"); | |
128 } | |
129 | |
130 context.AddOriginUnsafeToUseInCspViolation(url::Origin(GURL("http://a.com"))); | |
131 | |
132 // When the |blocked_url| and |source_location| are sensitive information. | |
133 { | |
134 EXPECT_FALSE(context.IsAllowedByCsp(CSPDirective::FrameSrc, blocked_url, | |
135 false, source_location)); | |
136 EXPECT_EQ(context.LastViolation().blocked_url, blocked_url.GetOrigin()); | |
137 EXPECT_EQ(context.LastViolation().source_location.url, ""); | |
138 EXPECT_EQ(context.LastViolation().source_location.line_number, 0u); | |
139 EXPECT_EQ(context.LastViolation().source_location.column_number, 0u); | |
140 EXPECT_EQ(context.LastViolation().console_message, | |
141 "Refused to frame 'http://a.com/' because it violates the " | |
142 "following Content Security Policy directive: \"frame-src " | |
143 "a.com/iframe\".\n"); | |
144 } | |
145 } | |
146 | |
89 } // namespace content | 147 } // namespace content |
OLD | NEW |