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

Unified Diff: third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp

Issue 2474903002: Part 3.1: Is policy list subsumed under subsuming policy? (Closed)
Patch Set: Rebasing Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
diff --git a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
index 2fcde837e88b691ee4073c580e1ce9c8423735d5..48c4aaeef6020f9b283d81659efab9571798a354 100644
--- a/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
+++ b/third_party/WebKit/Source/core/frame/csp/CSPDirectiveListTest.cpp
@@ -435,4 +435,327 @@ TEST_F(CSPDirectiveListTest, workerSrc) {
}
}
+TEST_F(CSPDirectiveListTest, SubsumesBasedOnCSPSourcesOnly) {
+ CSPDirectiveList* A = createList(
+ "script-src http://*.one.com; img-src https://one.com "
+ "http://two.com/imgs/",
+ ContentSecurityPolicyHeaderTypeEnforce);
+
+ struct TestCase {
+ const std::vector<const char*> policies;
+ bool expected;
+ bool expectedFirstPolicyOpposite;
+ } cases[] = {
+ // `listB`, which is not as restrictive as `A`, is not subsumed.
+ {{""}, false, true},
+ {{"script-src http://example.com"}, false, false},
+ {{"img-src http://example.com"}, false, false},
+ {{"script-src http://*.one.com"}, false, true},
+ {{"img-src https://one.com http://two.com/imgs/"}, false, true},
+ {{"default-src http://example.com"}, false, false},
+ {{"default-src https://one.com http://two.com/imgs/"}, false, false},
+ {{"default-src http://one.com"}, false, false},
+ {{"script-src http://*.one.com; img-src http://two.com/"}, false, false},
+ {{"script-src http://*.one.com", "img-src http://one.com"}, false, true},
+ {{"script-src http://*.one.com", "script-src https://two.com"},
+ false,
+ true},
+ {{"script-src http://*.random.com", "script-src https://random.com"},
+ false,
+ false},
+ {{"script-src http://one.com", "script-src https://random.com"},
+ false,
+ false},
+ {{"script-src http://*.random.com; default-src http://one.com "
+ "http://two.com/imgs/",
+ "default-src https://random.com"},
+ false,
+ false},
+ // `listB`, which is as restrictive as `A`, is subsumed.
+ {{"default-src https://one.com"}, true, false},
+ {{"default-src http://random.com",
+ "default-src https://non-random.com:*"},
+ true,
+ false},
+ {{"script-src http://*.one.com; img-src https://one.com"}, true, false},
+ {{"script-src http://*.one.com; img-src https://one.com "
+ "http://two.com/imgs/"},
+ true,
+ true},
+ {{"script-src http://*.one.com",
+ "img-src https://one.com http://two.com/imgs/"},
+ true,
+ true},
+ {{"script-src http://*.random.com; default-src https://one.com "
+ "http://two.com/imgs/",
+ "default-src https://else.com"},
+ true,
+ false},
+ {{"script-src http://*.random.com; default-src https://one.com "
+ "http://two.com/imgs/",
+ "default-src https://one.com"},
+ true,
+ false},
+ };
+
+ CSPDirectiveList* emptyA =
+ createList("", ContentSecurityPolicyHeaderTypeEnforce);
+
+ for (const auto& test : cases) {
+ HeapVector<Member<CSPDirectiveList>> listB;
+ for (const auto& policy : test.policies) {
+ listB.append(createList(policy, ContentSecurityPolicyHeaderTypeEnforce));
+ }
+
+ EXPECT_EQ(test.expected, A->subsumes(listB));
+ // Empty CSPDirective subsumes any list.
+ EXPECT_TRUE(emptyA->subsumes(listB));
+ // Check if first policy of `listB` subsumes `A`.
+ EXPECT_EQ(test.expectedFirstPolicyOpposite,
+ listB[0]->subsumes(HeapVector<Member<CSPDirectiveList>>(1, A)));
+ }
+}
+
+TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
+ enum DefaultBehaviour { Default, NoDefault, ChildAndDefault };
+
+ struct TestCase {
+ ContentSecurityPolicy::DirectiveType directive;
+ const DefaultBehaviour type;
+ } cases[] = {
+ // Directives with default directive.
+ {ContentSecurityPolicy::DirectiveType::ChildSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::FontSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::ImgSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::MediaSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default},
+ {ContentSecurityPolicy::DirectiveType::StyleSrc, Default},
+ // Directives with no default directive.
+ {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault},
+ {ContentSecurityPolicy::DirectiveType::DefaultSrc, NoDefault},
+ {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault},
+ {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault},
+ // Directive with multiple default directives.
+ {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault},
+ {ContentSecurityPolicy::DirectiveType::WorkerSrc, ChildAndDefault},
+ };
+
+ // Initial set-up.
+ std::stringstream allDirectives;
+ for (const auto& test : cases) {
+ const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
+ allDirectives << name << " http://" << name << ".com; ";
+ }
+ CSPDirectiveList* allDirectivesList = createList(
+ allDirectives.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce);
+ CSPDirectiveList* empty =
+ createList("", ContentSecurityPolicyHeaderTypeEnforce);
+
+ for (const auto& test : cases) {
+ const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
+ // When CSPDirectiveList is empty, then `null` should be returned for any
+ // type.
+ EXPECT_FALSE(empty->operativeDirective(test.directive));
+
+ // When all directives present, then given a type that directive value
+ // should be returned.
+ HeapVector<Member<CSPSource>> sources =
+ allDirectivesList->operativeDirective(test.directive)->m_list;
+ EXPECT_EQ(sources.size(), 1u);
+ EXPECT_TRUE(sources[0]->m_host.startsWith(name));
+
+ std::stringstream allExceptThis;
+ std::stringstream allExceptChildSrcAndThis;
+ for (const auto& subtest : cases) {
+ if (subtest.directive == test.directive)
+ continue;
+ const char* directiveName =
+ ContentSecurityPolicy::getDirectiveName(subtest.directive);
+ allExceptThis << directiveName << " http://" << directiveName << ".com; ";
+ if (subtest.directive != ContentSecurityPolicy::DirectiveType::ChildSrc) {
+ allExceptChildSrcAndThis << directiveName << " http://" << directiveName
+ << ".com; ";
+ }
+ }
+ CSPDirectiveList* allExceptThisList = createList(
+ allExceptThis.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce);
+ CSPDirectiveList* allExceptChildSrcAndThisList =
+ createList(allExceptChildSrcAndThis.str().c_str(),
+ ContentSecurityPolicyHeaderTypeEnforce);
+
+ switch (test.type) {
+ case Default:
+ sources = allExceptThisList->operativeDirective(test.directive)->m_list;
+ EXPECT_EQ(sources.size(), 1u);
+ EXPECT_EQ(sources[0]->m_host, "default-src.com");
+ break;
+ case NoDefault:
+ EXPECT_FALSE(allExceptThisList->operativeDirective(test.directive));
+ break;
+ case ChildAndDefault:
+ sources = allExceptThisList->operativeDirective(test.directive)->m_list;
+ EXPECT_EQ(sources.size(), 1u);
+ EXPECT_EQ(sources[0]->m_host, "child-src.com");
+ sources =
+ allExceptChildSrcAndThisList->operativeDirective(test.directive)
+ ->m_list;
+ EXPECT_EQ(sources.size(), 1u);
+ EXPECT_EQ(sources[0]->m_host, "default-src.com");
+ break;
+ }
+ }
+}
+
+TEST_F(CSPDirectiveListTest, GetSourceVector) {
+ const std::vector<const char*> policies = {
+ // Policy 1
+ "default-src https://default-src.com",
+ // Policy 2
+ "child-src http://child-src.com",
+ // Policy 3
+ "child-src http://child-src.com; default-src https://default-src.com",
+ // Policy 4
+ "base-uri http://base-uri.com",
+ // Policy 5
+ "frame-src http://frame-src.com"};
+
+ // Check expectations on the initial set-up.
+ HeapVector<Member<CSPDirectiveList>> policyVector;
+ for (const auto& policy : policies) {
+ policyVector.append(
+ createList(policy, ContentSecurityPolicyHeaderTypeEnforce));
+ }
+ HeapVector<Member<SourceListDirective>> result =
+ CSPDirectiveList::getSourceVector(
+ ContentSecurityPolicy::DirectiveType::DefaultSrc, policyVector);
+ EXPECT_EQ(result.size(), 2u);
+ result = CSPDirectiveList::getSourceVector(
+ ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector);
+ EXPECT_EQ(result.size(), 3u);
+ result = CSPDirectiveList::getSourceVector(
+ ContentSecurityPolicy::DirectiveType::BaseURI, policyVector);
+ EXPECT_EQ(result.size(), 1u);
+ result = CSPDirectiveList::getSourceVector(
+ ContentSecurityPolicy::DirectiveType::FrameSrc, policyVector);
+ EXPECT_EQ(result.size(), 4u);
+
+ enum DefaultBehaviour { Default, NoDefault, ChildAndDefault };
+
+ struct TestCase {
+ ContentSecurityPolicy::DirectiveType directive;
+ const DefaultBehaviour type;
+ size_t expectedTotal;
+ int expectedCurrent;
+ int expectedDefaultSrc;
+ int expectedChildSrc;
+ } cases[] = {
+ // Directives with default directive.
+ {ContentSecurityPolicy::DirectiveType::ChildSrc, Default, 4u, 3, 1, 3},
+ {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default, 3u, 1, 2, 0},
+ {ContentSecurityPolicy::DirectiveType::FontSrc, Default, 3u, 1, 2, 0},
+ {ContentSecurityPolicy::DirectiveType::ImgSrc, Default, 3u, 1, 2, 0},
+ {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default, 3u, 1, 2, 0},
+ {ContentSecurityPolicy::DirectiveType::MediaSrc, Default, 3u, 1, 2, 0},
+ {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default, 3u, 1, 2, 0},
+ {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default, 3u, 1, 2, 0},
+ {ContentSecurityPolicy::DirectiveType::StyleSrc, Default, 3u, 1, 2, 0},
+ // Directives with no default directive.
+ {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault, 2u, 2, 0, 0},
+ {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault, 1u, 1,
+ 0, 0},
+ {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault, 1u, 1, 0,
+ 0},
+ // Directive with multiple default directives.
+ {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault, 5u, 2,
+ 1, 2},
+ };
+
+ for (const auto& test : cases) {
+ // Initial set-up.
+ HeapVector<Member<CSPDirectiveList>> policyVector;
+ for (const auto& policy : policies) {
+ policyVector.append(
+ createList(policy, ContentSecurityPolicyHeaderTypeEnforce));
+ }
+ // Append current test's policy.
+ std::stringstream currentDirective;
+ const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
+ currentDirective << name << " http://" << name << ".com;";
+ policyVector.append(createList(currentDirective.str().c_str(),
+ ContentSecurityPolicyHeaderTypeEnforce));
+
+ HeapVector<Member<SourceListDirective>> result =
+ CSPDirectiveList::getSourceVector(test.directive, policyVector);
+
+ EXPECT_EQ(result.size(), test.expectedTotal);
+
+ int actualCurrent = 0, actualDefault = 0, actualChild = 0;
+ for (const auto& srcList : result) {
+ HeapVector<Member<CSPSource>> sources = srcList->m_list;
+ for (const auto& source : sources) {
+ if (source->m_host.startsWith(name))
+ actualCurrent += 1;
+ else if (source->m_host == "default-src.com")
+ actualDefault += 1;
+
+ if (source->m_host == "child-src.com")
+ actualChild += 1;
+ }
+ }
+
+ EXPECT_EQ(actualDefault, test.expectedDefaultSrc);
+ EXPECT_EQ(actualCurrent, test.expectedCurrent);
+ EXPECT_EQ(actualChild, test.expectedChildSrc);
+
+ // If another default-src is added that should only impact Fetch Directives
+ policyVector.append(createList("default-src https://default-src.com;",
+ ContentSecurityPolicyHeaderTypeEnforce));
+ size_t udpatedTotal =
+ test.type != NoDefault ? test.expectedTotal + 1 : test.expectedTotal;
+ EXPECT_EQ(
+ CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
+ udpatedTotal);
+ size_t expectedChildSrc =
+ test.directive == ContentSecurityPolicy::DirectiveType::ChildSrc ? 5u
+ : 4u;
+ EXPECT_EQ(CSPDirectiveList::getSourceVector(
+ ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
+ .size(),
+ expectedChildSrc);
+
+ // If another child-src is added that should only impact frame-src and
+ // child-src
+ policyVector.append(createList("child-src http://child-src.com;",
+ ContentSecurityPolicyHeaderTypeEnforce));
+ udpatedTotal =
+ test.type == ChildAndDefault ||
+ test.directive == ContentSecurityPolicy::DirectiveType::ChildSrc
+ ? udpatedTotal + 1
+ : udpatedTotal;
+ EXPECT_EQ(
+ CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
+ udpatedTotal);
+ expectedChildSrc = expectedChildSrc + 1u;
+ EXPECT_EQ(CSPDirectiveList::getSourceVector(
+ ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
+ .size(),
+ expectedChildSrc);
+
+ // If we add sandbox, nothing should change since it is currenly not
+ // considered.
+ policyVector.append(createList("sandbox http://sandbox.com;",
+ ContentSecurityPolicyHeaderTypeEnforce));
+ EXPECT_EQ(
+ CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
+ udpatedTotal);
+ EXPECT_EQ(CSPDirectiveList::getSourceVector(
+ ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
+ .size(),
+ expectedChildSrc);
+ }
+}
+
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/frame/csp/CSPDirectiveList.cpp ('k') | third_party/WebKit/Source/core/frame/csp/CSPSource.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698