Changeset 258631 in webkit
- Timestamp:
- Mar 18, 2020 7:49:37 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/imported/w3c/ChangeLog
r258553 r258631 1 2020-03-18 youenn fablet <youenn@apple.com> 2 3 Make sure a preflight fails if response headers are invalid 4 https://bugs.webkit.org/show_bug.cgi?id=208924 5 6 Reviewed by Alex Christensen. 7 8 * web-platform-tests/fetch/api/cors/cors-preflight-response-validation.any-expected.txt: Added. 9 * web-platform-tests/fetch/api/cors/cors-preflight-response-validation.any.html: Added. 10 * web-platform-tests/fetch/api/cors/cors-preflight-response-validation.any.js: Added. 11 (corsPreflightResponseValidation): 12 * web-platform-tests/fetch/api/cors/cors-preflight-response-validation.any.worker-expected.txt: Added. 13 * web-platform-tests/fetch/api/cors/cors-preflight-response-validation.any.worker.html: Added. 14 1 15 2020-03-17 Frederic Wang <fwang@igalia.com> 2 16 -
trunk/Source/WebCore/ChangeLog
r258630 r258631 1 2020-03-18 youenn fablet <youenn@apple.com> 2 3 Make sure a preflight fails if response headers are invalid 4 https://bugs.webkit.org/show_bug.cgi?id=208924 5 6 Reviewed by Alex Christensen. 7 8 Implement https://fetch.spec.whatwg.org/#cors-preflight-fetch-0 step 7.3. 9 In case header parsing is wrong, fail the preflight with a meaningful message. 10 Update parsing of headers to return an Optional so that parsing error is handled as a nullopt. 11 Minor refactoring to return Expected/Optional for error handlng instead of passing an out parameter. 12 Also, adding preflight cache entry if it is valid, no matter whether preflight succeeds or not. 13 14 Tests: imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-response-validation.any.html 15 imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-response-validation.any.worker.html 16 17 * loader/CrossOriginAccessControl.cpp: 18 (WebCore::validatePreflightResponse): 19 * loader/CrossOriginPreflightResultCache.cpp: 20 (WebCore::CrossOriginPreflightResultCacheItem::create): 21 (WebCore::CrossOriginPreflightResultCacheItem::validateMethodAndHeaders const): 22 * loader/CrossOriginPreflightResultCache.h: 23 (WebCore::CrossOriginPreflightResultCacheItem::CrossOriginPreflightResultCacheItem): 24 * platform/network/HTTPParsers.h: 25 (WebCore::parseAccessControlAllowList): 26 * platform/network/ResourceResponseBase.cpp: 27 (WebCore::ResourceResponseBase::filter): 28 (WebCore::ResourceResponseBase::sanitizeHTTPHeaderFieldsAccordingToTainting): 29 1 30 2020-03-18 Joonghun Park <jh718.park@samsung.com> 2 31 -
trunk/Source/WebCore/loader/CrossOriginAccessControl.cpp
r258052 r258631 265 265 return accessControlCheckResult; 266 266 267 auto result = makeUnique<CrossOriginPreflightResultCacheItem>(storedCredentialsPolicy); 268 String errorDescription; 269 // FIXME: allowsCrossOriginMethod and allowsCrossOriginHeaders should return Expected<void, String> to avoid having an out parameter. 270 if (!result->parse(response) 271 || !result->allowsCrossOriginMethod(request.httpMethod(), storedCredentialsPolicy, errorDescription) 272 || !result->allowsCrossOriginHeaders(request.httpHeaderFields(), storedCredentialsPolicy, errorDescription)) { 273 return makeUnexpected(errorDescription); 274 } 275 276 CrossOriginPreflightResultCache::singleton().appendEntry(securityOrigin.toString(), request.url(), WTFMove(result)); 267 auto result = CrossOriginPreflightResultCacheItem::create(storedCredentialsPolicy, response); 268 if (!result.has_value()) 269 return makeUnexpected(WTFMove(result.error())); 270 271 auto entry = WTFMove(result.value()); 272 auto errorDescription = entry->validateMethodAndHeaders(request.httpMethod(), request.httpHeaderFields()); 273 CrossOriginPreflightResultCache::singleton().appendEntry(securityOrigin.toString(), request.url(), entry.moveToUniquePtr()); 274 275 if (errorDescription) 276 return makeUnexpected(WTFMove(*errorDescription)); 277 277 278 return { }; 278 279 } -
trunk/Source/WebCore/loader/CrossOriginPreflightResultCache.cpp
r246238 r258631 53 53 } 54 54 55 bool CrossOriginPreflightResultCacheItem::parse(const ResourceResponse& response)55 Expected<UniqueRef<CrossOriginPreflightResultCacheItem>, String> CrossOriginPreflightResultCacheItem::create(StoredCredentialsPolicy policy, const ResourceResponse& response) 56 56 { 57 m_methods = parseAccessControlAllowList(response.httpHeaderField(HTTPHeaderName::AccessControlAllowMethods)); 58 m_headers = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(response.httpHeaderField(HTTPHeaderName::AccessControlAllowHeaders)); 57 auto methods = parseAccessControlAllowList(response.httpHeaderField(HTTPHeaderName::AccessControlAllowMethods)); 58 if (!methods) 59 return makeUnexpected(makeString("Header Access-Control-Allow-Methods has an invalid value: ", response.httpHeaderField(HTTPHeaderName::AccessControlAllowMethods))); 60 61 auto headers = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(response.httpHeaderField(HTTPHeaderName::AccessControlAllowHeaders)); 62 if (!headers) 63 return makeUnexpected(makeString("Header Access-Control-Allow-Headers has an invalid value: ", response.httpHeaderField(HTTPHeaderName::AccessControlAllowHeaders))); 59 64 60 65 Seconds expiryDelta = 0_s; … … 65 70 expiryDelta = defaultPreflightCacheTimeout; 66 71 67 m_absoluteExpiryTime = MonotonicTime::now() + expiryDelta; 68 return true; 72 return makeUniqueRef<CrossOriginPreflightResultCacheItem>(MonotonicTime::now() + expiryDelta, policy, WTFMove(*methods), WTFMove(*headers)); 73 } 74 75 Optional<String> CrossOriginPreflightResultCacheItem::validateMethodAndHeaders(const String& method, const HTTPHeaderMap& requestHeaders) const 76 { 77 String errorDescription; 78 if (!allowsCrossOriginMethod(method, m_storedCredentialsPolicy, errorDescription)) 79 return WTFMove(errorDescription); 80 if (!allowsCrossOriginHeaders(requestHeaders, m_storedCredentialsPolicy, errorDescription)) 81 return WTFMove(errorDescription); 82 return { }; 69 83 } 70 84 -
trunk/Source/WebCore/loader/CrossOriginPreflightResultCache.h
r246238 r258631 28 28 29 29 #include "StoredCredentialsPolicy.h" 30 #include <wtf/Expected.h> 30 31 #include <wtf/HashMap.h> 31 32 #include <wtf/HashSet.h> 32 33 #include <wtf/MonotonicTime.h> 33 34 #include <wtf/URLHash.h> 35 #include <wtf/UniqueRef.h> 34 36 35 37 namespace WebCore { … … 41 43 WTF_MAKE_NONCOPYABLE(CrossOriginPreflightResultCacheItem); WTF_MAKE_FAST_ALLOCATED; 42 44 public: 43 explicit CrossOriginPreflightResultCacheItem(StoredCredentialsPolicy storedCredentialsPolicy) 44 : m_storedCredentialsPolicy(storedCredentialsPolicy) 45 { 46 } 45 static Expected<UniqueRef<CrossOriginPreflightResultCacheItem>, String> create(StoredCredentialsPolicy, const ResourceResponse&); 47 46 48 WEBCORE_EXPORT bool parse(const ResourceResponse&);49 WEBCORE_EXPORT bool allowsCrossOriginMethod(const String&, StoredCredentialsPolicy, String& errorDescription) const; 50 WEBCORE_EXPORT bool allowsCrossOriginHeaders(const HTTPHeaderMap&, StoredCredentialsPolicy, String& errorDescription) const;51 bool allowsRequest(StoredCredentialsPolicy, const String& method, const HTTPHeaderMap& requestHeaders) const;47 CrossOriginPreflightResultCacheItem(MonotonicTime, StoredCredentialsPolicy, HashSet<String>&&, HashSet<String, ASCIICaseInsensitiveHash>&&); 48 49 Optional<String> validateMethodAndHeaders(const String& method, const HTTPHeaderMap&) const; 50 bool allowsRequest(StoredCredentialsPolicy, const String& method, const HTTPHeaderMap&) const; 52 51 53 52 private: 53 bool allowsCrossOriginMethod(const String&, StoredCredentialsPolicy, String& errorDescription) const; 54 bool allowsCrossOriginHeaders(const HTTPHeaderMap&, StoredCredentialsPolicy, String& errorDescription) const; 55 54 56 // FIXME: A better solution to holding onto the absolute expiration time might be 55 57 // to start a timer for the expiration delta that removes this from the cache when … … 76 78 }; 77 79 80 inline CrossOriginPreflightResultCacheItem::CrossOriginPreflightResultCacheItem(MonotonicTime absoluteExpiryTime, StoredCredentialsPolicy storedCredentialsPolicy, HashSet<String>&& methods, HashSet<String, ASCIICaseInsensitiveHash>&& headers) 81 : m_absoluteExpiryTime(absoluteExpiryTime) 82 , m_storedCredentialsPolicy(storedCredentialsPolicy) 83 , m_methods(WTFMove(methods)) 84 , m_headers(WTFMove(headers)) 85 { 86 } 87 78 88 } // namespace WebCore -
trunk/Source/WebCore/platform/network/HTTPParsers.h
r256013 r258631 157 157 158 158 template<class HashType = DefaultHash<String>::Hash> 159 HashSet<String, HashType> parseAccessControlAllowList(const String& string)159 Optional<HashSet<String, HashType>> parseAccessControlAllowList(const String& string) 160 160 { 161 161 HashSet<String, HashType> set; … … 173 173 return { }; 174 174 } 175 return set;175 return WTFMove(set); 176 176 } 177 177 -
trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp
r258458 r258631 181 181 filteredResponse.setType(Type::Cors); 182 182 183 auto accessControlExposeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(response.httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders)) ;183 auto accessControlExposeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(response.httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders)).valueOr(HashSet<String, ASCIICaseInsensitiveHash> { }); 184 184 if (performCheck == PerformExposeAllHeadersCheck::Yes && accessControlExposeHeaderSet.contains("*")) 185 185 return filteredResponse; … … 447 447 return; 448 448 case ResourceResponse::Tainting::Cors: { 449 auto corsSafeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders)) ;449 auto corsSafeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders)).valueOr(HashSet<String, ASCIICaseInsensitiveHash> { }); 450 450 if (corsSafeHeaderSet.contains("*")) 451 451 return;
Note: See TracChangeset
for help on using the changeset viewer.