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

Side by Side 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 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "core/frame/csp/CSPDirectiveList.h" 5 #include "core/frame/csp/CSPDirectiveList.h"
6 6
7 #include "core/frame/csp/ContentSecurityPolicy.h" 7 #include "core/frame/csp/ContentSecurityPolicy.h"
8 #include "core/frame/csp/SourceListDirective.h" 8 #include "core/frame/csp/SourceListDirective.h"
9 #include "platform/network/ContentSecurityPolicyParsers.h" 9 #include "platform/network/ContentSecurityPolicyParsers.h"
10 #include "platform/network/ResourceRequest.h" 10 #include "platform/network/ResourceRequest.h"
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 KURL resource = KURL(KURL(), "https://example.test/worker.js"); 428 KURL resource = KURL(KURL(), "https://example.test/worker.js");
429 Member<CSPDirectiveList> directiveList = 429 Member<CSPDirectiveList> directiveList =
430 createList(test.list, ContentSecurityPolicyHeaderTypeEnforce); 430 createList(test.list, ContentSecurityPolicyHeaderTypeEnforce);
431 EXPECT_EQ(test.allowed, 431 EXPECT_EQ(test.allowed,
432 directiveList->allowWorkerFromSource( 432 directiveList->allowWorkerFromSource(
433 resource, ResourceRequest::RedirectStatus::NoRedirect, 433 resource, ResourceRequest::RedirectStatus::NoRedirect,
434 ContentSecurityPolicy::SuppressReport)); 434 ContentSecurityPolicy::SuppressReport));
435 } 435 }
436 } 436 }
437 437
438 TEST_F(CSPDirectiveListTest, SubsumesBasedOnCSPSourcesOnly) {
439 CSPDirectiveList* A = createList(
440 "script-src http://*.one.com; img-src https://one.com "
441 "http://two.com/imgs/",
442 ContentSecurityPolicyHeaderTypeEnforce);
443
444 struct TestCase {
445 const std::vector<const char*> policies;
446 bool expected;
447 bool expectedFirstPolicyOpposite;
448 } cases[] = {
449 // `listB`, which is not as restrictive as `A`, is not subsumed.
450 {{""}, false, true},
451 {{"script-src http://example.com"}, false, false},
452 {{"img-src http://example.com"}, false, false},
453 {{"script-src http://*.one.com"}, false, true},
454 {{"img-src https://one.com http://two.com/imgs/"}, false, true},
455 {{"default-src http://example.com"}, false, false},
456 {{"default-src https://one.com http://two.com/imgs/"}, false, false},
457 {{"default-src http://one.com"}, false, false},
458 {{"script-src http://*.one.com; img-src http://two.com/"}, false, false},
459 {{"script-src http://*.one.com", "img-src http://one.com"}, false, true},
460 {{"script-src http://*.one.com", "script-src https://two.com"},
461 false,
462 true},
463 {{"script-src http://*.random.com", "script-src https://random.com"},
464 false,
465 false},
466 {{"script-src http://one.com", "script-src https://random.com"},
467 false,
468 false},
469 {{"script-src http://*.random.com; default-src http://one.com "
470 "http://two.com/imgs/",
471 "default-src https://random.com"},
472 false,
473 false},
474 // `listB`, which is as restrictive as `A`, is subsumed.
475 {{"default-src https://one.com"}, true, false},
476 {{"default-src http://random.com",
477 "default-src https://non-random.com:*"},
478 true,
479 false},
480 {{"script-src http://*.one.com; img-src https://one.com"}, true, false},
481 {{"script-src http://*.one.com; img-src https://one.com "
482 "http://two.com/imgs/"},
483 true,
484 true},
485 {{"script-src http://*.one.com",
486 "img-src https://one.com http://two.com/imgs/"},
487 true,
488 true},
489 {{"script-src http://*.random.com; default-src https://one.com "
490 "http://two.com/imgs/",
491 "default-src https://else.com"},
492 true,
493 false},
494 {{"script-src http://*.random.com; default-src https://one.com "
495 "http://two.com/imgs/",
496 "default-src https://one.com"},
497 true,
498 false},
499 };
500
501 CSPDirectiveList* emptyA =
502 createList("", ContentSecurityPolicyHeaderTypeEnforce);
503
504 for (const auto& test : cases) {
505 HeapVector<Member<CSPDirectiveList>> listB;
506 for (const auto& policy : test.policies) {
507 listB.append(createList(policy, ContentSecurityPolicyHeaderTypeEnforce));
508 }
509
510 EXPECT_EQ(test.expected, A->subsumes(listB));
511 // Empty CSPDirective subsumes any list.
512 EXPECT_TRUE(emptyA->subsumes(listB));
513 // Check if first policy of `listB` subsumes `A`.
514 EXPECT_EQ(test.expectedFirstPolicyOpposite,
515 listB[0]->subsumes(HeapVector<Member<CSPDirectiveList>>(1, A)));
516 }
517 }
518
519 TEST_F(CSPDirectiveListTest, OperativeDirectiveGivenType) {
520 enum DefaultBehaviour { Default, NoDefault, ChildAndDefault };
521
522 struct TestCase {
523 ContentSecurityPolicy::DirectiveType directive;
524 const DefaultBehaviour type;
525 } cases[] = {
526 // Directives with default directive.
527 {ContentSecurityPolicy::DirectiveType::ChildSrc, Default},
528 {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default},
529 {ContentSecurityPolicy::DirectiveType::FontSrc, Default},
530 {ContentSecurityPolicy::DirectiveType::ImgSrc, Default},
531 {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default},
532 {ContentSecurityPolicy::DirectiveType::MediaSrc, Default},
533 {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default},
534 {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default},
535 {ContentSecurityPolicy::DirectiveType::StyleSrc, Default},
536 // Directives with no default directive.
537 {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault},
538 {ContentSecurityPolicy::DirectiveType::DefaultSrc, NoDefault},
539 {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault},
540 {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault},
541 // Directive with multiple default directives.
542 {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault},
543 {ContentSecurityPolicy::DirectiveType::WorkerSrc, ChildAndDefault},
544 };
545
546 // Initial set-up.
547 std::stringstream allDirectives;
548 for (const auto& test : cases) {
549 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
550 allDirectives << name << " http://" << name << ".com; ";
551 }
552 CSPDirectiveList* allDirectivesList = createList(
553 allDirectives.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce);
554 CSPDirectiveList* empty =
555 createList("", ContentSecurityPolicyHeaderTypeEnforce);
556
557 for (const auto& test : cases) {
558 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
559 // When CSPDirectiveList is empty, then `null` should be returned for any
560 // type.
561 EXPECT_FALSE(empty->operativeDirective(test.directive));
562
563 // When all directives present, then given a type that directive value
564 // should be returned.
565 HeapVector<Member<CSPSource>> sources =
566 allDirectivesList->operativeDirective(test.directive)->m_list;
567 EXPECT_EQ(sources.size(), 1u);
568 EXPECT_TRUE(sources[0]->m_host.startsWith(name));
569
570 std::stringstream allExceptThis;
571 std::stringstream allExceptChildSrcAndThis;
572 for (const auto& subtest : cases) {
573 if (subtest.directive == test.directive)
574 continue;
575 const char* directiveName =
576 ContentSecurityPolicy::getDirectiveName(subtest.directive);
577 allExceptThis << directiveName << " http://" << directiveName << ".com; ";
578 if (subtest.directive != ContentSecurityPolicy::DirectiveType::ChildSrc) {
579 allExceptChildSrcAndThis << directiveName << " http://" << directiveName
580 << ".com; ";
581 }
582 }
583 CSPDirectiveList* allExceptThisList = createList(
584 allExceptThis.str().c_str(), ContentSecurityPolicyHeaderTypeEnforce);
585 CSPDirectiveList* allExceptChildSrcAndThisList =
586 createList(allExceptChildSrcAndThis.str().c_str(),
587 ContentSecurityPolicyHeaderTypeEnforce);
588
589 switch (test.type) {
590 case Default:
591 sources = allExceptThisList->operativeDirective(test.directive)->m_list;
592 EXPECT_EQ(sources.size(), 1u);
593 EXPECT_EQ(sources[0]->m_host, "default-src.com");
594 break;
595 case NoDefault:
596 EXPECT_FALSE(allExceptThisList->operativeDirective(test.directive));
597 break;
598 case ChildAndDefault:
599 sources = allExceptThisList->operativeDirective(test.directive)->m_list;
600 EXPECT_EQ(sources.size(), 1u);
601 EXPECT_EQ(sources[0]->m_host, "child-src.com");
602 sources =
603 allExceptChildSrcAndThisList->operativeDirective(test.directive)
604 ->m_list;
605 EXPECT_EQ(sources.size(), 1u);
606 EXPECT_EQ(sources[0]->m_host, "default-src.com");
607 break;
608 }
609 }
610 }
611
612 TEST_F(CSPDirectiveListTest, GetSourceVector) {
613 const std::vector<const char*> policies = {
614 // Policy 1
615 "default-src https://default-src.com",
616 // Policy 2
617 "child-src http://child-src.com",
618 // Policy 3
619 "child-src http://child-src.com; default-src https://default-src.com",
620 // Policy 4
621 "base-uri http://base-uri.com",
622 // Policy 5
623 "frame-src http://frame-src.com"};
624
625 // Check expectations on the initial set-up.
626 HeapVector<Member<CSPDirectiveList>> policyVector;
627 for (const auto& policy : policies) {
628 policyVector.append(
629 createList(policy, ContentSecurityPolicyHeaderTypeEnforce));
630 }
631 HeapVector<Member<SourceListDirective>> result =
632 CSPDirectiveList::getSourceVector(
633 ContentSecurityPolicy::DirectiveType::DefaultSrc, policyVector);
634 EXPECT_EQ(result.size(), 2u);
635 result = CSPDirectiveList::getSourceVector(
636 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector);
637 EXPECT_EQ(result.size(), 3u);
638 result = CSPDirectiveList::getSourceVector(
639 ContentSecurityPolicy::DirectiveType::BaseURI, policyVector);
640 EXPECT_EQ(result.size(), 1u);
641 result = CSPDirectiveList::getSourceVector(
642 ContentSecurityPolicy::DirectiveType::FrameSrc, policyVector);
643 EXPECT_EQ(result.size(), 4u);
644
645 enum DefaultBehaviour { Default, NoDefault, ChildAndDefault };
646
647 struct TestCase {
648 ContentSecurityPolicy::DirectiveType directive;
649 const DefaultBehaviour type;
650 size_t expectedTotal;
651 int expectedCurrent;
652 int expectedDefaultSrc;
653 int expectedChildSrc;
654 } cases[] = {
655 // Directives with default directive.
656 {ContentSecurityPolicy::DirectiveType::ChildSrc, Default, 4u, 3, 1, 3},
657 {ContentSecurityPolicy::DirectiveType::ConnectSrc, Default, 3u, 1, 2, 0},
658 {ContentSecurityPolicy::DirectiveType::FontSrc, Default, 3u, 1, 2, 0},
659 {ContentSecurityPolicy::DirectiveType::ImgSrc, Default, 3u, 1, 2, 0},
660 {ContentSecurityPolicy::DirectiveType::ManifestSrc, Default, 3u, 1, 2, 0},
661 {ContentSecurityPolicy::DirectiveType::MediaSrc, Default, 3u, 1, 2, 0},
662 {ContentSecurityPolicy::DirectiveType::ObjectSrc, Default, 3u, 1, 2, 0},
663 {ContentSecurityPolicy::DirectiveType::ScriptSrc, Default, 3u, 1, 2, 0},
664 {ContentSecurityPolicy::DirectiveType::StyleSrc, Default, 3u, 1, 2, 0},
665 // Directives with no default directive.
666 {ContentSecurityPolicy::DirectiveType::BaseURI, NoDefault, 2u, 2, 0, 0},
667 {ContentSecurityPolicy::DirectiveType::FrameAncestors, NoDefault, 1u, 1,
668 0, 0},
669 {ContentSecurityPolicy::DirectiveType::FormAction, NoDefault, 1u, 1, 0,
670 0},
671 // Directive with multiple default directives.
672 {ContentSecurityPolicy::DirectiveType::FrameSrc, ChildAndDefault, 5u, 2,
673 1, 2},
674 };
675
676 for (const auto& test : cases) {
677 // Initial set-up.
678 HeapVector<Member<CSPDirectiveList>> policyVector;
679 for (const auto& policy : policies) {
680 policyVector.append(
681 createList(policy, ContentSecurityPolicyHeaderTypeEnforce));
682 }
683 // Append current test's policy.
684 std::stringstream currentDirective;
685 const char* name = ContentSecurityPolicy::getDirectiveName(test.directive);
686 currentDirective << name << " http://" << name << ".com;";
687 policyVector.append(createList(currentDirective.str().c_str(),
688 ContentSecurityPolicyHeaderTypeEnforce));
689
690 HeapVector<Member<SourceListDirective>> result =
691 CSPDirectiveList::getSourceVector(test.directive, policyVector);
692
693 EXPECT_EQ(result.size(), test.expectedTotal);
694
695 int actualCurrent = 0, actualDefault = 0, actualChild = 0;
696 for (const auto& srcList : result) {
697 HeapVector<Member<CSPSource>> sources = srcList->m_list;
698 for (const auto& source : sources) {
699 if (source->m_host.startsWith(name))
700 actualCurrent += 1;
701 else if (source->m_host == "default-src.com")
702 actualDefault += 1;
703
704 if (source->m_host == "child-src.com")
705 actualChild += 1;
706 }
707 }
708
709 EXPECT_EQ(actualDefault, test.expectedDefaultSrc);
710 EXPECT_EQ(actualCurrent, test.expectedCurrent);
711 EXPECT_EQ(actualChild, test.expectedChildSrc);
712
713 // If another default-src is added that should only impact Fetch Directives
714 policyVector.append(createList("default-src https://default-src.com;",
715 ContentSecurityPolicyHeaderTypeEnforce));
716 size_t udpatedTotal =
717 test.type != NoDefault ? test.expectedTotal + 1 : test.expectedTotal;
718 EXPECT_EQ(
719 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
720 udpatedTotal);
721 size_t expectedChildSrc =
722 test.directive == ContentSecurityPolicy::DirectiveType::ChildSrc ? 5u
723 : 4u;
724 EXPECT_EQ(CSPDirectiveList::getSourceVector(
725 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
726 .size(),
727 expectedChildSrc);
728
729 // If another child-src is added that should only impact frame-src and
730 // child-src
731 policyVector.append(createList("child-src http://child-src.com;",
732 ContentSecurityPolicyHeaderTypeEnforce));
733 udpatedTotal =
734 test.type == ChildAndDefault ||
735 test.directive == ContentSecurityPolicy::DirectiveType::ChildSrc
736 ? udpatedTotal + 1
737 : udpatedTotal;
738 EXPECT_EQ(
739 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
740 udpatedTotal);
741 expectedChildSrc = expectedChildSrc + 1u;
742 EXPECT_EQ(CSPDirectiveList::getSourceVector(
743 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
744 .size(),
745 expectedChildSrc);
746
747 // If we add sandbox, nothing should change since it is currenly not
748 // considered.
749 policyVector.append(createList("sandbox http://sandbox.com;",
750 ContentSecurityPolicyHeaderTypeEnforce));
751 EXPECT_EQ(
752 CSPDirectiveList::getSourceVector(test.directive, policyVector).size(),
753 udpatedTotal);
754 EXPECT_EQ(CSPDirectiveList::getSourceVector(
755 ContentSecurityPolicy::DirectiveType::ChildSrc, policyVector)
756 .size(),
757 expectedChildSrc);
758 }
759 }
760
438 } // namespace blink 761 } // namespace blink
OLDNEW
« 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