Changeset 205455 in webkit


Ignore:
Timestamp:
Sep 5, 2016 9:58:48 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

Clean CSS stylesheets should be accessible from JavaScript
https://bugs.webkit.org/show_bug.cgi?id=158728

Patch by Youenn Fablet <youenn@apple.com> on 2016-09-05
Reviewed by Darin Adler.

Source/WebCore:

Covered by updated tests.

Making use of the resource response type to evaluate whether to make the CSS stylesheets visible
for stylesheet link elements and for stylesheet processing instructions.
Ideally, the origin flag should be a boolean.

To keep behavior consistent in cors-check-unaware cases, the flag might remain unset.
In that case, the behavior remains the same (checking of the stylesheet URL).
The origin flag is set to true or false only in case of fetch mode being set to cors using the crossorigin attribute.

Updated CSSStyleSheet::create to take a Node reference. Updated callers accordingly.

  • contentextensions/ContentExtensionStyleSheet.cpp:

(WebCore::ContentExtensions::ContentExtensionStyleSheet::ContentExtensionStyleSheet): Updated to pass a Node reference and not pointer.

  • css/CSSStyleSheet.cpp:

(WebCore::CSSStyleSheet::create): Makes origin flag undefined if boolean parameter is not passed.
Otherwise origin flag is set according given boolean value.
(WebCore::CSSStyleSheet::createInline): Makes origin flag set to true.
(WebCore::CSSStyleSheet::CSSStyleSheet): Adding origin flag initialization.
(WebCore::CSSStyleSheet::canAccessRules): Returning according the origin flag if set.
Returning as before in case the flag is not set.

  • css/CSSStyleSheet.h: Adding origin clean flag.
  • dom/ExtensionStyleSheets.cpp:

(WebCore::ExtensionStyleSheets::addUserStyleSheet):
(WebCore::ExtensionStyleSheets::addAuthorStyleSheetForTesting):
(WebCore::ExtensionStyleSheets::maybeAddContentExtensionSheet):

  • html/HTMLLinkElement.cpp:

(WebCore::HTMLLinkElement::initializeStyleSheet): Helper routine used in setCSSStyleSheet.
Sets origin clean flag if the resource is clean.
(WebCore::HTMLLinkElement::setCSSStyleSheet): Making use of initializeStyleSheet.

  • html/HTMLLinkElement.h:

LayoutTests:

  • http/tests/security/cannot-read-cssrules-expected.txt:
  • http/tests/security/cannot-read-cssrules-redirect-expected.txt:
  • http/tests/security/cannot-read-cssrules-redirect.html:
  • http/tests/security/cannot-read-cssrules.html:
  • http/tests/security/cross-origin-css-9.html:
  • http/tests/security/resources/xorigincss1-allow-star.php: Added.
Location:
trunk
Files:
1 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r205451 r205455  
     12016-09-05  Youenn Fablet  <youenn@apple.com>
     2
     3        Clean CSS stylesheets should be accessible from JavaScript
     4        https://bugs.webkit.org/show_bug.cgi?id=158728
     5
     6        Reviewed by Darin Adler.
     7
     8        * http/tests/security/cannot-read-cssrules-expected.txt:
     9        * http/tests/security/cannot-read-cssrules-redirect-expected.txt:
     10        * http/tests/security/cannot-read-cssrules-redirect.html:
     11        * http/tests/security/cannot-read-cssrules.html:
     12        * http/tests/security/cross-origin-css-9.html:
     13        * http/tests/security/resources/xorigincss1-allow-star.php: Added.
     14
    1152016-09-05  Philippe Normand  <pnormand@igalia.com>
    216
  • trunk/LayoutTests/http/tests/security/cannot-read-cssrules-expected.txt

    r50587 r205455  
     1CONSOLE MESSAGE: Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
    12This test whether a script can read the rules from a cross-origin style sheet. For more information on why we block this, please see https://bugs.webkit.org/show_bug.cgi?id=20527.
    23
    34Test begins.
    4 == Cross-Origin ==
     5== Cross-Origin resource, no-cors mode ==
    56cssRules: null
    67rules: null
    7 == Same-Origin ==
     8== Same-Origin resource, no-cors mode ==
    89cssRules: [object CSSRuleList]
     10cssRules length: 1
    911rules: [object CSSRuleList]
     12rules length: 1
     13== Cross-Origin resource, cors mode, failing cors check ==
     14cssRules: null
     15rules: null
     16== Cross-Origin resource, cors mode, successful cors check ==
     17cssRules: [object CSSRuleList]
     18cssRules length: 1
     19rules: [object CSSRuleList]
     20rules length: 1
    1021Test ends.
  • trunk/LayoutTests/http/tests/security/cannot-read-cssrules-redirect-expected.txt

    r50587 r205455  
     1CONSOLE MESSAGE: Cross-origin redirection to http://127.0.0.1:8000/security/resources/xorigincss1.css denied by Cross-Origin Resource Sharing policy: Origin http://127.0.0.1:8000 is not allowed by Access-Control-Allow-Origin.
    12This test whether a script can read the rules from a cross-origin style sheet in the presence of redirects. For more information on why we block this, please see https://bugs.webkit.org/show_bug.cgi?id=20527.
    23
    34Test begins.
    4 == Same-Origin to Cross-Origin ==
     5== Same-Origin to Cross-Origin, no-cors mode ==
    56cssRules: null
    67rules: null
    7 == Cross-Origin to Same-Origin ==
     8== Cross-Origin to Same-Origin, no-cors mode ==
    89cssRules: [object CSSRuleList]
     10cssRules length: 1
    911rules: [object CSSRuleList]
     12rules length: 1
     13== Same-Origin to Same-Origin, cors mode ==
     14cssRules: [object CSSRuleList]
     15cssRules length: 1
     16rules: [object CSSRuleList]
     17rules length: 1
     18== Cross-Origin to Same-Origin, cors mode, successful cors check ==
     19cssRules: [object CSSRuleList]
     20cssRules length: 1
     21rules: [object CSSRuleList]
     22rules length: 1
     23== Cross-Origin to Same-Origin, cors mode, failing cors check ==
     24cssRules: null
     25rules: null
    1026Test ends.
  • trunk/LayoutTests/http/tests/security/cannot-read-cssrules-redirect.html

    r153915 r205455  
    66<link rel="stylesheet"
    77      href="http://localhost:8000/resources/redirect.php?url=http://127.0.0.1:8000/security/resources/cssStyle.css">
     8<link rel="stylesheet"
     9      href="/resources/redirect.php?url=http://127.0.0.1:8000/security/resources/cssStyle.css" crossorigin="">
     10<link rel="stylesheet"
     11      href="http://localhost:8000/security/resources/redirect-allow-star.php?url=http://127.0.0.1:8000/security/resources/xorigincss1-allow-star.php" crossorigin="">
     12<link rel="stylesheet"
     13      href="http://localhost:8000/resources/redirect.php?url=http://127.0.0.1:8000/security/resources/xorigincss1.css" crossorigin="">
    814<script>
    915if (window.testRunner)
     
    1622}
    1723
     24function checkCSSRules(sheet)
     25{
     26    try {
     27        var cssRules = sheet.cssRules;
     28        log("cssRules: " + cssRules);
     29        if (cssRules)
     30            log("cssRules length: " + cssRules.length);
     31    } catch(e) {
     32        log("exception thrown for cssRules: " + e);
     33    }
     34    try {
     35        var rules = sheet.rules;
     36        log("rules: " + rules);
     37        if (rules)
     38            log("rules length: " + rules.length);
     39    } catch(e) {
     40        log("exception thrown for rules: " + e);
     41    }
     42}
     43
    1844window.onload = function() {
    1945    log("Test begins.");
    20     log("== Same-Origin to Cross-Origin ==");
    21     var sheet1 = document.styleSheets[0];
    22     log("cssRules: " + sheet1.cssRules);
    23     log("rules: " + sheet1.rules);
    24     log("== Cross-Origin to Same-Origin ==");
    25     var sheet2 = document.styleSheets[1];
    26     log("cssRules: " + sheet2.cssRules);
    27     log("rules: " + sheet2.rules);
     46    log("== Same-Origin to Cross-Origin, no-cors mode ==");
     47    checkCSSRules(document.styleSheets[0]);
     48    log("== Cross-Origin to Same-Origin, no-cors mode ==");
     49    checkCSSRules(document.styleSheets[1]);
     50    log("== Same-Origin to Same-Origin, cors mode ==");
     51    checkCSSRules(document.styleSheets[2]);
     52    log("== Cross-Origin to Same-Origin, cors mode, successful cors check ==");
     53    checkCSSRules(document.styleSheets[3]);
     54    log("== Cross-Origin to Same-Origin, cors mode, failing cors check ==");
     55    checkCSSRules(document.styleSheets[4]);
    2856    log("Test ends.");
    2957}
  • trunk/LayoutTests/http/tests/security/cannot-read-cssrules.html

    r120174 r205455  
    55      href="http://localhost:8000/security/resources/cssStyle.css">
    66<link rel="stylesheet" href="resources/cssStyle.css">
     7<link rel="stylesheet"
     8      href="http://localhost:8000/security/resources/cssStyle.css" crossorigin="">
     9<link rel="stylesheet"
     10      href="http://localhost:8000/security/resources/xorigincss1-allow-star.php" crossorigin="">
    711<script>
    812if (window.testRunner)
     
    1519}
    1620
     21function checkCSSRules(sheet)
     22{
     23    try {
     24        var cssRules = sheet.cssRules;
     25        log("cssRules: " + cssRules);
     26        if (cssRules)
     27            log("cssRules length: " + cssRules.length);
     28    } catch(e) {
     29        log("exception thrown for cssRules: " + e);
     30    }
     31    try {
     32        var rules = sheet.rules;
     33        log("rules: " + rules);
     34        if (rules)
     35            log("rules length: " + rules.length);
     36    } catch(e) {
     37        log("exception thrown for rules: " + e);
     38    }
     39}
     40
    1741window.onload = function() {
    1842    log("Test begins.");
    19     log("== Cross-Origin ==");
    20     var sheet1 = document.styleSheets[0];
    21     log("cssRules: " + sheet1.cssRules);
    22     log("rules: " + sheet1.rules);
    23     log("== Same-Origin ==");
    24     var sheet2 = document.styleSheets[1];
    25     log("cssRules: " + sheet2.cssRules);
    26     log("rules: " + sheet2.rules);
     43    log("== Cross-Origin resource, no-cors mode ==");
     44    checkCSSRules(document.styleSheets[0]);
     45    log("== Same-Origin resource, no-cors mode ==");
     46    checkCSSRules(document.styleSheets[1]);
     47    log("== Cross-Origin resource, cors mode, failing cors check ==");
     48    checkCSSRules(document.styleSheets[2]);
     49    log("== Cross-Origin resource, cors mode, successful cors check ==");
     50    checkCSSRules(document.styleSheets[3]);
    2751    log("Test ends.");
    2852}
  • trunk/LayoutTests/http/tests/security/cross-origin-css-9.html

    r201930 r205455  
    2222    expectedColor = expectToIncludeOrigin ? "rgb(255, 255, 0)" : "rgb(0, 0, 255)";
    2323    assert_equals(getBackgroundColorForId(id), expectedColor);
    24     // FIXME: cssRules should be made visible according resource tainted status, not only based on the resource URL being cross origin.
    25     // assert_equals(document.getElementById("link-" + id).sheet.cssRules !== null, expectVisibility);
     24    assert_equals(document.getElementById("link-" + id).sheet.cssRules !== null, expectVisibility);
    2625}
    2726
  • trunk/Source/WebCore/ChangeLog

    r205450 r205455  
     12016-09-05  Youenn Fablet  <youenn@apple.com>
     2
     3        Clean CSS stylesheets should be accessible from JavaScript
     4        https://bugs.webkit.org/show_bug.cgi?id=158728
     5
     6        Reviewed by Darin Adler.
     7
     8        Covered by updated tests.
     9
     10        Making use of the resource response type to evaluate whether to make the CSS stylesheets visible
     11        for stylesheet link elements and for stylesheet processing instructions.
     12        Ideally, the origin flag should be a boolean.
     13
     14        To keep behavior consistent in cors-check-unaware cases, the flag might remain unset.
     15        In that case, the behavior remains the same (checking of the stylesheet URL).
     16        The origin flag is set to true or false only in case of fetch mode being set to cors using the crossorigin attribute.
     17
     18        Updated CSSStyleSheet::create to take a Node reference. Updated callers accordingly.
     19
     20        * contentextensions/ContentExtensionStyleSheet.cpp:
     21        (WebCore::ContentExtensions::ContentExtensionStyleSheet::ContentExtensionStyleSheet): Updated to pass a Node reference and not pointer.
     22        * css/CSSStyleSheet.cpp:
     23        (WebCore::CSSStyleSheet::create): Makes origin flag undefined if boolean parameter is not passed.
     24        Otherwise origin flag is set according given boolean value.
     25        (WebCore::CSSStyleSheet::createInline): Makes origin flag set to true.
     26        (WebCore::CSSStyleSheet::CSSStyleSheet): Adding origin flag initialization.
     27        (WebCore::CSSStyleSheet::canAccessRules): Returning according the origin flag if set.
     28        Returning as before in case the flag is not set.
     29        * css/CSSStyleSheet.h: Adding origin clean flag.
     30        * dom/ExtensionStyleSheets.cpp:
     31        (WebCore::ExtensionStyleSheets::addUserStyleSheet):
     32        (WebCore::ExtensionStyleSheets::addAuthorStyleSheetForTesting):
     33        (WebCore::ExtensionStyleSheets::maybeAddContentExtensionSheet):
     34        * html/HTMLLinkElement.cpp:
     35        (WebCore::HTMLLinkElement::initializeStyleSheet): Helper routine used in setCSSStyleSheet.
     36        Sets origin clean flag if the resource is clean.
     37        (WebCore::HTMLLinkElement::setCSSStyleSheet): Making use of initializeStyleSheet.
     38        * html/HTMLLinkElement.h:
     39
    1402016-09-05  Youenn Fablet  <youenn@apple.com>
    241
  • trunk/Source/WebCore/contentextensions/ContentExtensionStyleSheet.cpp

    r203240 r205455  
    3939
    4040ContentExtensionStyleSheet::ContentExtensionStyleSheet(Document& document)
    41     : m_styleSheet(CSSStyleSheet::create(StyleSheetContents::create(), &document))
     41    : m_styleSheet(CSSStyleSheet::create(StyleSheetContents::create(), document))
    4242{
    4343    m_styleSheet->contents().setIsUserStyleSheet(true);
  • trunk/Source/WebCore/css/CSSStyleSheet.cpp

    r205093 r205455  
    7979
    8080Ref<CSSStyleSheet> CSSStyleSheet::create(Ref<StyleSheetContents>&& sheet, CSSImportRule* ownerRule)
    81 { 
     81{
    8282    return adoptRef(*new CSSStyleSheet(WTFMove(sheet), ownerRule));
    8383}
    8484
    85 Ref<CSSStyleSheet> CSSStyleSheet::create(Ref<StyleSheetContents>&& sheet, Node* ownerNode)
    86 { 
    87     return adoptRef(*new CSSStyleSheet(WTFMove(sheet), ownerNode, TextPosition::minimumPosition(), false));
     85Ref<CSSStyleSheet> CSSStyleSheet::create(Ref<StyleSheetContents>&& sheet, Node& ownerNode, const Optional<bool>& isCleanOrigin)
     86{
     87    return adoptRef(*new CSSStyleSheet(WTFMove(sheet), ownerNode, TextPosition::minimumPosition(), false, isCleanOrigin));
    8888}
    8989
     
    9191{
    9292    CSSParserContext parserContext(ownerNode.document(), baseURL, encoding);
    93     return adoptRef(*new CSSStyleSheet(StyleSheetContents::create(baseURL.string(), parserContext), &ownerNode, startPosition, true));
     93    return adoptRef(*new CSSStyleSheet(StyleSheetContents::create(baseURL.string(), parserContext), ownerNode, startPosition, true, true));
    9494}
    9595
     
    106106}
    107107
    108 CSSStyleSheet::CSSStyleSheet(Ref<StyleSheetContents>&& contents, Node* ownerNode, const TextPosition& startPosition, bool isInlineStylesheet)
     108CSSStyleSheet::CSSStyleSheet(Ref<StyleSheetContents>&& contents, Node& ownerNode, const TextPosition& startPosition, bool isInlineStylesheet, const Optional<bool>& isOriginClean)
    109109    : m_contents(WTFMove(contents))
    110110    , m_isInlineStylesheet(isInlineStylesheet)
    111111    , m_isDisabled(false)
    112112    , m_mutatedRules(false)
    113     , m_ownerNode(ownerNode)
     113    , m_isOriginClean(isOriginClean)
     114    , m_ownerNode(&ownerNode)
    114115    , m_ownerRule(0)
    115116    , m_startPosition(startPosition)
    116117{
    117     ASSERT(isAcceptableCSSStyleSheetParent(ownerNode));
     118    ASSERT(isAcceptableCSSStyleSheetParent(&ownerNode));
    118119    m_contents->registerClient(this);
    119120}
     
    259260bool CSSStyleSheet::canAccessRules() const
    260261{
    261     if (m_isInlineStylesheet)
    262         return true;
     262    if (m_isOriginClean)
     263        return m_isOriginClean.value();
     264
    263265    URL baseURL = m_contents->baseURL();
    264266    if (baseURL.isEmpty())
     
    267269    if (!document)
    268270        return true;
    269     if (document->securityOrigin()->canRequest(baseURL))
    270         return true;
    271     return false;
     271    return document->securityOrigin()->canRequest(baseURL);
    272272}
    273273
  • trunk/Source/WebCore/css/CSSStyleSheet.h

    r205093 r205455  
    5050public:
    5151    static Ref<CSSStyleSheet> create(Ref<StyleSheetContents>&&, CSSImportRule* ownerRule = 0);
    52     static Ref<CSSStyleSheet> create(Ref<StyleSheetContents>&&, Node* ownerNode);
     52    static Ref<CSSStyleSheet> create(Ref<StyleSheetContents>&&, Node& ownerNode, const Optional<bool>& isOriginClean = Nullopt);
    5353    static Ref<CSSStyleSheet> createInline(Node&, const URL&, const TextPosition& startPosition = TextPosition::minimumPosition(), const String& encoding = String());
    5454
     
    126126    CSSStyleSheet(Ref<StyleSheetContents>&&, CSSImportRule* ownerRule);
    127127    CSSStyleSheet(Ref<StyleSheetContents>&&, Node* ownerNode, const TextPosition& startPosition, bool isInlineStylesheet);
     128    CSSStyleSheet(Ref<StyleSheetContents>&&, Node& ownerNode, const TextPosition& startPosition, bool isInlineStylesheet, const Optional<bool>&);
    128129
    129130    bool isCSSStyleSheet() const final { return true; }
     
    131132
    132133    bool canAccessRules() const;
    133    
     134
    134135    Ref<StyleSheetContents> m_contents;
    135136    bool m_isInlineStylesheet;
    136137    bool m_isDisabled;
    137138    bool m_mutatedRules;
     139    Optional<bool> m_isOriginClean;
    138140    String m_title;
    139141    RefPtr<MediaQuerySet> m_mediaQueries;
  • trunk/Source/WebCore/dom/ExtensionStyleSheets.cpp

    r198180 r205455  
    161161{
    162162    ASSERT(userSheet.get().isUserStyleSheet());
    163     m_userStyleSheets.append(CSSStyleSheet::create(WTFMove(userSheet), &m_document));
     163    m_userStyleSheets.append(CSSStyleSheet::create(WTFMove(userSheet), m_document));
    164164    m_document.styleResolverChanged(RecalcStyleImmediately);
    165165}
     
    168168{
    169169    ASSERT(!authorSheet.get().isUserStyleSheet());
    170     m_authorStyleSheetsForTesting.append(CSSStyleSheet::create(WTFMove(authorSheet), &m_document));
     170    m_authorStyleSheetsForTesting.append(CSSStyleSheet::create(WTFMove(authorSheet), m_document));
    171171    m_document.styleResolverChanged(RecalcStyleImmediately);
    172172}
     
    192192        return;
    193193
    194     Ref<CSSStyleSheet> cssSheet = CSSStyleSheet::create(sheet, &m_document);
     194    Ref<CSSStyleSheet> cssSheet = CSSStyleSheet::create(sheet, m_document);
    195195    m_contentExtensionSheets.set(identifier, &cssSheet.get());
    196196    m_userStyleSheets.append(adoptRef(cssSheet.leakRef()));
  • trunk/Source/WebCore/dom/ProcessingInstruction.cpp

    r195927 r205455  
    191191    CSSParserContext parserContext(document(), baseURL, charset);
    192192
    193     auto cssSheet = CSSStyleSheet::create(StyleSheetContents::create(href, parserContext), this);
     193    auto cssSheet = CSSStyleSheet::create(StyleSheetContents::create(href, parserContext), *this);
    194194    cssSheet.get().setDisabled(m_alternate);
    195195    cssSheet.get().setTitle(m_title);
  • trunk/Source/WebCore/html/HTMLLinkElement.cpp

    r205269 r205455  
    340340}
    341341
     342void HTMLLinkElement::initializeStyleSheet(Ref<StyleSheetContents>&& styleSheet, const CachedCSSStyleSheet& cachedStyleSheet)
     343{
     344    // FIXME: originClean should be turned to false except if fetch mode is CORS.
     345    Optional<bool> originClean;
     346    if (cachedStyleSheet.options().mode == FetchOptions::Mode::Cors)
     347        originClean = cachedStyleSheet.isClean();
     348
     349    m_sheet = CSSStyleSheet::create(WTFMove(styleSheet), *this, originClean);
     350    m_sheet->setMediaQueries(MediaQuerySet::createAllowingDescriptionSyntax(m_media));
     351    m_sheet->setTitle(title());
     352}
     353
    342354void HTMLLinkElement::setCSSStyleSheet(const String& href, const URL& baseURL, const String& charset, const CachedCSSStyleSheet* cachedStyleSheet)
    343355{
     
    359371        ASSERT(restoredSheet->isCacheable());
    360372        ASSERT(!restoredSheet->isLoading());
    361 
    362         m_sheet = CSSStyleSheet::create(restoredSheet.releaseNonNull(), this);
    363         m_sheet->setMediaQueries(MediaQuerySet::createAllowingDescriptionSyntax(m_media));
    364         m_sheet->setTitle(title());
     373        initializeStyleSheet(restoredSheet.releaseNonNull(), *cachedStyleSheet);
    365374
    366375        m_loading = false;
     
    371380
    372381    auto styleSheet = StyleSheetContents::create(href, parserContext);
    373     m_sheet = CSSStyleSheet::create(styleSheet.copyRef(), this);
    374     m_sheet->setMediaQueries(MediaQuerySet::createAllowingDescriptionSyntax(m_media));
    375     m_sheet->setTitle(title());
     382    initializeStyleSheet(styleSheet.copyRef(), *cachedStyleSheet);
    376383
    377384    styleSheet.get().parseAuthorStyleSheet(cachedStyleSheet, document().securityOrigin());
  • trunk/Source/WebCore/html/HTMLLinkElement.h

    r205269 r205455  
    8383    void removedFrom(ContainerNode&) final;
    8484
     85    void initializeStyleSheet(Ref<StyleSheetContents>&&, const CachedCSSStyleSheet&);
     86
    8587    // from CachedResourceClient
    8688    void setCSSStyleSheet(const String& href, const URL& baseURL, const String& charset, const CachedCSSStyleSheet*) final;
Note: See TracChangeset for help on using the changeset viewer.