WebCore/dom/ProcessingInstruction.cpp

204204#endif
205205 RefPtr<CSSStyleSheet> newSheet = CSSStyleSheet::create(this, url, charset);
206206 m_sheet = newSheet;
207  parseStyleSheet(sheet->sheetText());
 207 // We don't need the cross-origin security check here because we are
 208 // getting the sheet text in "strict" mode. This enforces a valid CSS MIME
 209 // type.
 210 parseStyleSheet(sheet->sheetText(true));
208211 newSheet->setTitle(m_title);
209212 newSheet->setMedia(MediaList::create(newSheet.get(), m_media));
210213 newSheet->setDisabled(m_alternate);
50756

WebCore/ChangeLog

 12009-11-11 Chris Evans <cevans@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Adopt a more conservative approach for loading CSS cross-origin. When
 6 loading CSS cross-origin, it must be start with valid CSS if the MIME
 7 type is broken.
 8
 9 https://bugs.webkit.org/show_bug.cgi?id=29820
 10
 11 Test: http/tests/security/cross-origin-css.html
 12 Test: http/tests/security/cross-origin-css-in-xml.xml
 13
 14 * html/HTMLLinkElement.cpp:
 15 (WebCore::HTMLLinkElement::setCSSStyleSheet): Enforce stricter load
 16 requirements for cross-origin loads.
 17 * css/CSSImportRule.cpp:
 18 (WebCore::CSSImportRule::setCSSStyleSheet): Enforce stricter load
 19 requirements for cross-origin loads.
 20 * css/CSSStyleSheet.h:
 21 * css/CSSStyleSheet.cpp:
 22 * css/CSSParser.cpp:
 23 * css/CSSGrammar.y:
 24 * css/CSSParser.h:
 25 Add ability to tell whether the CSS parse started with a syntactically
 26 valid CSS rule.
 27 * loader/CachedCSSStyleSheet.h:
 28 * loader/CachedCSSStyleSheet.cpp:
 29 (WebCore::CachedCSSStyleSheet::sheetText): Add ability to return
 30 whether the MIME type was acceptable for CSS.
 31 (WebCore::CachedCSSStyleSheet::canUseSheet): If requested, return
 32 whether the MIME type was valid or not.
 33 * dom/ProcessingInstruction.cpp
 34 (WebCore::ProcessingInstruction::setCSSStyleSheet): Make use of strict
 35 mode explicit and add comment.
 36
1372009-11-10 Keishi Hattori <casey.hattori@gmail.com>
238
339 Reviewed by Timothy Hatcher.
50756

WebCore/html/HTMLLinkElement.cpp

259259
260260 bool strictParsing = !document()->inCompatMode();
261261 bool enforceMIMEType = strictParsing;
 262 bool crossOriginCSS = false;
 263 bool validMIMEType = false;
262264
263265 // Check to see if we should enforce the MIME type of the CSS resource in strict mode.
264266 // Running in iWeb 2 is one example of where we don't want to - <rdar://problem/6099748>
265267 if (enforceMIMEType && document()->page() && !document()->page()->settings()->enforceCSSMIMETypeInStrictMode())
266268 enforceMIMEType = false;
267269
268  String sheetText = sheet->sheetText(enforceMIMEType);
 270 // If we're loading a stylesheet cross-origin, and the MIME type is not
 271 // standard, require the CSS to at least start with a syntactically
 272 // valid CSS rule.
 273 // This prevents an attacker playing games by injecting CSS strings into
 274 // HTML, XML, JSON, etc. etc.
 275 if (!document()->securityOrigin()->canRequest(KURL(ParsedURLString, url)))
 276 crossOriginCSS = true;
 277
 278 String sheetText = sheet->sheetText(enforceMIMEType, &validMIMEType);
269279 m_sheet->parseString(sheetText, strictParsing);
 280 if (crossOriginCSS && !validMIMEType && !m_sheet->hasSyntacticallyValidCSSHeader())
 281 m_sheet = CSSStyleSheet::create(this, url, charset);
270282
271283 if (strictParsing && document()->settings() && document()->settings()->needsSiteSpecificQuirks()) {
272284 // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>.
50756

WebCore/css/CSSStyleSheet.cpp

4242 , m_loadCompleted(false)
4343 , m_strictParsing(!parentSheet || parentSheet->useStrictParsing())
4444 , m_isUserStyleSheet(parentSheet ? parentSheet->isUserStyleSheet() : false)
 45 , m_hasSyntacticallyValidCSSHeader(true)
4546{
4647}
4748

5354 , m_loadCompleted(false)
5455 , m_strictParsing(false)
5556 , m_isUserStyleSheet(false)
 57 , m_hasSyntacticallyValidCSSHeader(true)
5658{
5759}
5860

6264 , m_charset(charset)
6365 , m_loadCompleted(false)
6466 , m_strictParsing(!ownerRule || ownerRule->useStrictParsing())
 67 , m_hasSyntacticallyValidCSSHeader(true)
6568{
6669 CSSStyleSheet* parentSheet = ownerRule ? ownerRule->parentStyleSheet() : 0;
6770 m_doc = parentSheet ? parentSheet->doc() : 0;
50756

WebCore/css/CSSStyleSheet.h

9595
9696 void setIsUserStyleSheet(bool b) { m_isUserStyleSheet = b; }
9797 bool isUserStyleSheet() const { return m_isUserStyleSheet; }
 98 void setHasSyntacticallyValidCSSHeader(bool b) { m_hasSyntacticallyValidCSSHeader = b; }
 99 bool hasSyntacticallyValidCSSHeader() const { return m_hasSyntacticallyValidCSSHeader; }
98100
99101private:
100102 CSSStyleSheet(Node* ownerNode, const String& href, const String& charset);

110112 bool m_loadCompleted : 1;
111113 bool m_strictParsing : 1;
112114 bool m_isUserStyleSheet : 1;
 115 bool m_hasSyntacticallyValidCSSHeader : 1;
113116};
114117
115118} // namespace
50756

WebCore/css/CSSParser.cpp

139139 , m_currentShorthand(0)
140140 , m_implicitShorthand(false)
141141 , m_hasFontFaceOnlyValues(false)
 142 , m_hadSyntacticallyValidCSSRule(false)
142143 , m_defaultNamespace(starAtom)
143144 , m_data(0)
144145 , yy_start(1)

51695170 return keyframePtr;
51705171}
51715172
 5173void CSSParser::invalidBlockHit()
 5174{
 5175 if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
 5176 m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
 5177}
 5178
51725179static int cssPropertyID(const UChar* propertyName, unsigned length)
51735180{
51745181 if (!length)
50756

WebCore/css/CSSGrammar.y

416416 ;
417417
418418rule:
419  valid_rule
 419 valid_rule {
 420 static_cast<CSSParser*>(parser)->m_hadSyntacticallyValidCSSRule = true;
 421 }
420422 | invalid_rule
421423 | invalid_at
422424 | invalid_import

15171519 ;
15181520
15191521invalid_block:
1520  '{' error invalid_block_list error closing_brace
1521  | '{' error closing_brace
 1522 '{' error invalid_block_list error closing_brace {
 1523 static_cast<CSSParser*>(parser)->invalidBlockHit();
 1524 }
 1525 | '{' error closing_brace {
 1526 static_cast<CSSParser*>(parser)->invalidBlockHit();
 1527 }
15221528 ;
15231529
15241530invalid_block_list:
50756

WebCore/css/CSSParser.h

191191 bool addVariableDeclarationBlock(const CSSParserString&);
192192 bool checkForVariables(CSSParserValueList*);
193193 void addUnresolvedProperty(int propId, bool important);
 194 void invalidBlockHit();
194195
195196 Vector<CSSSelector*>* reusableSelectorVector() { return &m_reusableSelectorVector; }
196197

212213 bool m_implicitShorthand;
213214
214215 bool m_hasFontFaceOnlyValues;
 216 bool m_hadSyntacticallyValidCSSRule;
215217
216218 Vector<String> m_variableNames;
217219 Vector<RefPtr<CSSValue> > m_variableValues;
50756

WebCore/css/CSSImportRule.cpp

2626#include "DocLoader.h"
2727#include "Document.h"
2828#include "MediaList.h"
 29#include "SecurityOrigin.h"
2930#include "Settings.h"
3031#include <wtf/StdLibExtras.h>
3132

6162 m_styleSheet = CSSStyleSheet::create(this, url, charset);
6263
6364 CSSStyleSheet* parent = parentStyleSheet();
64  bool strict = !parent || parent->useStrictParsing();
65  String sheetText = sheet->sheetText(strict);
66  m_styleSheet->parseString(sheetText, strict);
 65 bool enforceMIMEType = !parent || parent->useStrictParsing();
 66 bool crossOriginCSS = false;
 67 bool validMIMEType = false;
 68 if (!parent->doc() || !parent->doc()->securityOrigin()->canRequest(KURL(ParsedURLString, url)))
 69 crossOriginCSS = true;
6770
68  if (strict && parent && parent->doc() && parent->doc()->settings() && parent->doc()->settings()->needsSiteSpecificQuirks()) {
 71 String sheetText = sheet->sheetText(enforceMIMEType, &validMIMEType);
 72 m_styleSheet->parseString(sheetText, enforceMIMEType);
 73 if (crossOriginCSS && !validMIMEType && !m_styleSheet->hasSyntacticallyValidCSSHeader())
 74 m_styleSheet = CSSStyleSheet::create(this, url, charset);
 75
 76 if (enforceMIMEType && parent && parent->doc() && parent->doc()->settings() && parent->doc()->settings()->needsSiteSpecificQuirks()) {
6977 // Work around <https://bugs.webkit.org/show_bug.cgi?id=28350>.
7078 DEFINE_STATIC_LOCAL(const String, slashKHTMLFixesDotCss, ("/KHTMLFixes.css"));
7179 DEFINE_STATIC_LOCAL(const String, mediaWikiKHTMLFixesStyleSheet, ("/* KHTML fix stylesheet */\n/* work around the horizontal scrollbars */\n#column-content { margin-left: 0; }\n\n"));
50756

WebCore/loader/CachedCSSStyleSheet.h

4040 CachedCSSStyleSheet(const String& URL, const String& charset);
4141 virtual ~CachedCSSStyleSheet();
4242
43  const String sheetText(bool enforceMIMEType = true) const;
 43 const String sheetText(bool enforceMIMEType = true, bool* hasValidMIMEType = 0) const;
4444
4545 virtual void didAddClient(CachedResourceClient*);
4646

5656 void checkNotify();
5757
5858 private:
59  bool canUseSheet(bool enforceMIMEType) const;
 59 bool canUseSheet(bool enforceMIMEType, bool* hasValidMIMEType) const;
6060
6161 protected:
6262 RefPtr<TextResourceDecoder> m_decoder;
50756

WebCore/loader/CachedCSSStyleSheet.cpp

7171 return m_decoder->encoding().name();
7272}
7373
74 const String CachedCSSStyleSheet::sheetText(bool enforceMIMEType) const
 74const String CachedCSSStyleSheet::sheetText(bool enforceMIMEType, bool* hasValidMIMEType) const
7575{
7676 ASSERT(!isPurgeable());
7777
78  if (!m_data || m_data->isEmpty() || !canUseSheet(enforceMIMEType))
 78 if (!m_data || m_data->isEmpty() || !canUseSheet(enforceMIMEType, hasValidMIMEType))
7979 return String();
8080
8181 if (!m_decodedSheetText.isNull())

122122 checkNotify();
123123}
124124
125 bool CachedCSSStyleSheet::canUseSheet(bool enforceMIMEType) const
 125bool CachedCSSStyleSheet::canUseSheet(bool enforceMIMEType, bool* hasValidMIMEType) const
126126{
127127 if (errorOccurred())
128128 return false;
129129
130  if (!enforceMIMEType)
 130 if (!enforceMIMEType && !hasValidMIMEType)
131131 return true;
132132
133133 // This check exactly matches Firefox. Note that we grab the Content-Type

138138 // This code defaults to allowing the stylesheet for non-HTTP protocols so
139139 // folks can use standards mode for local HTML documents.
140140 String mimeType = extractMIMETypeFromMediaType(response().httpHeaderField("Content-Type"));
141  return mimeType.isEmpty() || equalIgnoringCase(mimeType, "text/css") || equalIgnoringCase(mimeType, "application/x-unknown-content-type");
 141 bool typeOK = mimeType.isEmpty() || equalIgnoringCase(mimeType, "text/css") || equalIgnoringCase(mimeType, "application/x-unknown-content-type");
 142 if (hasValidMIMEType)
 143 *hasValidMIMEType = typeOK;
 144 if (!enforceMIMEType)
 145 return true;
 146 return typeOK;
142147}
143148
144149}
50756

LayoutTests/http/tests/security/resources/xorigincss4.html

 1.id5 {
 2 background-color: yellow;
 3}
0

LayoutTests/http/tests/security/resources/xorigincss1.html

 1.id1 {
 2 nosuchproperty: blahblah;
 3 background-color: yellow;
 4}
0

LayoutTests/http/tests/security/resources/xorigincss5.html

 1<html>{}
 2.id7 {
 3 background-color: yellow;
 4}
 5</html>
0

LayoutTests/http/tests/security/resources/xorigincss1.css

 1<html>{}
 2.id3 {
 3 background-color: yellow;
 4}
 5</html>
0

LayoutTests/http/tests/security/resources/xorigincss2.css

 1<html>{}
 2.id6 {
 3 background-color: yellow;
 4}
 5</html>
0

LayoutTests/http/tests/security/resources/xorigincss2.html

 1<html>{}
 2.id2 {
 3 background-color: yellow;
 4}
 5</html>
0

LayoutTests/http/tests/security/resources/xorigincss6.html

 1#id1 {
 2 background-color: yellow;
 3}
0

LayoutTests/http/tests/security/resources/xorigincss3.html

 1<html>{}
 2.id4 {
 3 background-color: yellow;
 4}
 5</html>
0

LayoutTests/http/tests/security/cross-origin-css-expected.txt

 1LINK Cross-origin, HTML, valid: rgb(255, 255, 0)
 2LINK + IMPORT Cross-origin, HTML, invalid: rgba(0, 0, 0, 0)
 3LINK Cross-origin, CSS, invalid: rgb(255, 255, 0)
 4LINK Same-origin, HTML, invalid: rgb(255, 255, 0)
 5IMPORT Cross-origin, HTML, valid: rgb(255, 255, 0)
 6IMPORT Cross-origin, CSS, invalid: rgb(255, 255, 0)
 7IMPORT Same-origin, HTML, invalid: rgb(255, 255, 0)
0

LayoutTests/http/tests/security/cross-origin-css-in-xml-expected.txt

 1XML CSS Same-origin, HTML, valid: rgba(0, 0, 0, 0)
0

LayoutTests/http/tests/security/cross-origin-css-in-xml.xml

 1<?xml version="1.0" encoding="UTF-8"?>
 2<?xml-stylesheet type="text/css" href="resources/xorigincss6.html"?>
 3<html xmlns="http://www.w3.org/1999/xhtml">
 4<head>
 5<script>
 6if (window.layoutTestController) {
 7 layoutTestController.waitUntilDone();
 8 layoutTestController.dumpAsText();
 9}
 10
 11window.onload = function() {
 12 ele = document.getElementById("id1");
 13 // For now, simply test that an invalid MIME type (HTML) is rejected due to
 14 // strict mode. It doesn't matter if we test same-origin or cross-origin.
 15 ele.innerText = "XML CSS Same-origin, HTML, valid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 16
 17 if (window.layoutTestController)
 18 layoutTestController.notifyDone();
 19}
 20</script>
 21</head>
 22<body><div id="id1"></div></body>
 23</html>
0

LayoutTests/http/tests/security/cross-origin-css.html

 1<html>
 2<head>
 3<link rel="stylesheet"
 4 href="resources/redir.php?url=http://localhost:8000/security/resources/xorigincss1.html"></link>
 5<link rel="stylesheet"
 6 type="text/css"
 7 href="resources/redir.php?url=http://localhost:8000/security/resources/xorigincss2.html"></link>
 8<link rel="stylesheet"
 9 href="resources/redir.php?url=http://localhost:8000/security/resources/xorigincss1.css"></link>
 10<link rel="stylesheet"
 11 href="resources/xorigincss3.html"></link>
 12<script>
 13if (window.layoutTestController) {
 14 layoutTestController.waitUntilDone();
 15 layoutTestController.dumpAsText();
 16}
 17
 18window.onload = function() {
 19 ele = document.getElementById("id1");
 20 ele.innerText = "LINK Cross-origin, HTML, valid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 21 ele = document.getElementById("id2");
 22 ele.innerText = "LINK + IMPORT Cross-origin, HTML, invalid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 23 ele = document.getElementById("id3");
 24 ele.innerText = "LINK Cross-origin, CSS, invalid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 25 ele = document.getElementById("id4");
 26 ele.innerText = "LINK Same-origin, HTML, invalid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 27 ele = document.getElementById("id5");
 28 ele.innerText = "IMPORT Cross-origin, HTML, valid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 29 ele = document.getElementById("id6");
 30 ele.innerText = "IMPORT Cross-origin, CSS, invalid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 31 ele = document.getElementById("id7");
 32 ele.innerText = "IMPORT Same-origin, HTML, invalid: " + window.getComputedStyle(ele, null).getPropertyValue('background-color');
 33
 34 if (window.layoutTestController)
 35 layoutTestController.notifyDone();
 36}
 37</script>
 38<style>
 39/* Deliberately reuse the same file / class / id on this first one */
 40@import "resources/redir.php?url=http://localhost:8000/security/resources/xorigincss2.html";
 41@import "resources/redir.php?url=http://localhost:8000/security/resources/xorigincss4.html";
 42@import "resources/redir.php?url=http://localhost:8000/security/resources/xorigincss2.css";
 43@import "resources/xorigincss5.html";
 44</style>
 45</head>
 46<body><div id="id1" class="id1"></div><div id="id2" class="id2"></div><div id="id3" class="id3"></div><div id="id4" class="id4"></div><div id="id5" class="id5"></div><div id="id6" class="id6"></div><div id="id7" class="id7"></div></body>
 47</html>
0

LayoutTests/ChangeLog

 12009-11-11 Chris Evans <cevans@chromium.org>
 2
 3 Reviewed by NOBODY (OOPS!).
 4
 5 Test for https://bugs.webkit.org/show_bug.cgi?id=29820
 6 Adopt a more conservative approach for loading CSS cross-origin.
 7
 8 * http/tests/security/cross-origin-css.html: Added.
 9 * http/tests/security/cross-origin-css-expected.txt: Added.
 10 * http/tests/security/cross-origin-css-in-xml.xml: Added.
 11 * http/tests/security/cross-origin-css-in-xml-expected.txt: Added.
 12 * http/tests/security/resources/xorigincss1.css: Added.
 13 * http/tests/security/resources/xorigincss2.css: Added.
 14 * http/tests/security/resources/xorigincss1.html: Added.
 15 * http/tests/security/resources/xorigincss2.html: Added.
 16 * http/tests/security/resources/xorigincss3.html: Added.
 17 * http/tests/security/resources/xorigincss4.html: Added.
 18 * http/tests/security/resources/xorigincss5.html: Added.
 19 * http/tests/security/resources/xorigincss6.html: Added.
 20
1212009-11-10 Philippe Normand <pnormand@igalia.com>
222
323 Reviewed by Eric Seidel.
50756