Title: [239393] branches/safari-606-branch

Diff

Modified: branches/safari-606-branch/LayoutTests/ChangeLog (239392 => 239393)


--- branches/safari-606-branch/LayoutTests/ChangeLog	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/LayoutTests/ChangeLog	2018-12-19 22:05:29 UTC (rev 239393)
@@ -1,3 +1,26 @@
+2018-12-19  Kocsen Chung  <[email protected]>
+
+        Apply patch. rdar://problem/46848447
+
+    2018-12-19  John Wilander  <[email protected]>
+
+            Cap lifetime of persistent cookies created client-side through document.cookie
+            https://bugs.webkit.org/show_bug.cgi?id=189933
+            <rdar://problem/44741888>
+
+            Reviewed by Chris Dumez.
+
+            * TestExpectations:
+                Skipped the new test by default since the behavior change is for
+                Cocoa platforms only.
+            * http/tests/cookies/capped-lifetime-for-cookie-set-in-js-expected.txt: Added.
+            * http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html: Added.
+            * http/tests/cookies/resources/cookie-utilities.js:
+            * platform/ios/TestExpectations:
+                Marked the new test as [ Pass ].
+            * platform/mac-wk2/TestExpectations:
+                Marked the new test as [ Pass ].
+
 2018-12-14  Alan Coon  <[email protected]>
 
         Apply patch. rdar://problem/46603448

Modified: branches/safari-606-branch/LayoutTests/TestExpectations (239392 => 239393)


--- branches/safari-606-branch/LayoutTests/TestExpectations	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/LayoutTests/TestExpectations	2018-12-19 22:05:29 UTC (rev 239393)
@@ -150,6 +150,7 @@
 http/tests/loading/basic-auth-remove-credentials.html [ Skip ]
 http/tests/security/strip-referrer-to-origin-for-third-party-redirects-in-private-mode.html [ Skip ]
 http/tests/security/strip-referrer-to-origin-for-third-party-requests-in-private-mode.html [ Skip ]
+http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html [ Skip ]
 
 # ApplePay is only available on iOS (greater than iOS 10) and macOS (greater than macOS 10.12) and only for WebKit2.
 http/tests/ssl/applepay/ [ Skip ]

Added: branches/safari-606-branch/LayoutTests/http/tests/cookies/capped-lifetime-for-cookie-set-in-js-expected.txt (0 => 239393)


--- branches/safari-606-branch/LayoutTests/http/tests/cookies/capped-lifetime-for-cookie-set-in-js-expected.txt	                        (rev 0)
+++ branches/safari-606-branch/LayoutTests/http/tests/cookies/capped-lifetime-for-cookie-set-in-js-expected.txt	2018-12-19 22:05:29 UTC (rev 239393)
@@ -0,0 +1,11 @@
+Check that cookies created by _javascript_ with max-age or expiry longer than a week get capped to a week.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS The two short-lived cookies don't expire after more than 172830 seconds.
+PASS The two long-lived cookies don't expire after more than 604830 seconds.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: branches/safari-606-branch/LayoutTests/http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html (0 => 239393)


--- branches/safari-606-branch/LayoutTests/http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html	                        (rev 0)
+++ branches/safari-606-branch/LayoutTests/http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html	2018-12-19 22:05:29 UTC (rev 239393)
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src=""
+    <script src=""
+</head>
+<body>
+<script>
+    description("Check that cookies created by _javascript_ with max-age or expiry longer than a week get capped to a week.");
+    jsTestIsAsync = true;
+
+    let passedTests = 0;
+    function checkThatCookieDoesNotExpireAfter(cookieData, maxAgeInSeconds) {
+        let now = new Date();
+        let maxExpiryDateInMilliseconds = now.getTime() + (maxAgeInSeconds * 1000);
+
+        if (maxExpiryDateInMilliseconds > cookieData["expires"])
+            ++passedTests;
+        else
+            testFailed("Cookie named " + cookieData["name"] + " expires in more than " + maxAgeInSeconds + " seconds.");
+    }
+
+    const twoDaysInSeconds = 2 * 24 * 60 * 60;
+    const shortLivedCookieMaxAge = { name : "shortLivedCookieMaxAge", lifetime : "Max-Age=" + twoDaysInSeconds + ";" };
+    document.cookie = shortLivedCookieMaxAge.name + "=foobar; " + shortLivedCookieMaxAge.lifetime + " path=/";
+
+    const twoDaysAsExpiresDate = createExpiresDateFromMaxAge(twoDaysInSeconds);
+    const shortLivedCookieExpires = { name : "shortLivedCookieExpires", lifetime : "Expires=" + twoDaysAsExpiresDate + ";" };
+    document.cookie = shortLivedCookieExpires.name + "=foobar; " + shortLivedCookieExpires.lifetime + " path=/";
+
+    const _oneWeekInSeconds_ = 7 * 24 * 60 * 60;
+    const twoWeeksInSeconds = 2 * oneWeekInSeconds;
+    const longLivedCookieMaxAge = { name : "longLivedCookieMaxAge", lifetime : "Max-Age=" + twoWeeksInSeconds + ";" };
+    document.cookie = longLivedCookieMaxAge.name + "=foobar; " + longLivedCookieMaxAge.lifetime + " path=/";
+
+    const twoWeeksAsExpiresDate = createExpiresDateFromMaxAge(twoWeeksInSeconds);
+    const longLivedCookieExpires = { name : "longLivedCookieExpires", lifetime : "Expires=" + twoWeeksAsExpiresDate + ";" };
+    document.cookie = longLivedCookieExpires.name + "=foobar; " + longLivedCookieExpires.lifetime + " path=/";
+
+    const overTwoDaysInSeconds = twoDaysInSeconds + 30;
+    const overOneWeekInSeconds = oneWeekInSeconds + 30;
+    if (internals) {
+        let cookies = internals.getCookies();
+        if (!cookies.length)
+            testFailed("No cookies found.");
+        for (let cookie of cookies) {
+            switch (cookie.name) {
+                case shortLivedCookieMaxAge.name:
+                    checkThatCookieDoesNotExpireAfter(cookie, overTwoDaysInSeconds);
+                    break;
+                case shortLivedCookieExpires.name:
+                    checkThatCookieDoesNotExpireAfter(cookie, overTwoDaysInSeconds);
+                    break;
+                case longLivedCookieMaxAge.name:
+                    checkThatCookieDoesNotExpireAfter(cookie, overOneWeekInSeconds);
+                    break;
+                case longLivedCookieExpires.name:
+                    checkThatCookieDoesNotExpireAfter(cookie, overOneWeekInSeconds);
+                    break;
+            }
+        }
+        if (passedTests === 4) {
+            testPassed("The two short-lived cookies don't expire after more than " + overTwoDaysInSeconds + " seconds.");
+            testPassed("The two long-lived cookies don't expire after more than " + overOneWeekInSeconds + " seconds.");
+        } else
+            testFailed("At least one cookie's expiry attribute was beyond the test thresholds.");
+    } else
+        testFailed("No internals object.");
+
+    finishJSTest();
+</script>
+</body>
+</html>

Modified: branches/safari-606-branch/LayoutTests/http/tests/cookies/resources/cookie-utilities.js (239392 => 239393)


--- branches/safari-606-branch/LayoutTests/http/tests/cookies/resources/cookie-utilities.js	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/LayoutTests/http/tests/cookies/resources/cookie-utilities.js	2018-12-19 22:05:29 UTC (rev 239393)
@@ -237,3 +237,10 @@
     });
     return promise;
 }
+
+function createExpiresDateFromMaxAge(maxAgeInSeconds)
+{
+    let date = new Date();
+    date.setTime(date.getTime() + (maxAgeInSeconds * 1000));
+    return date.toUTCString();
+}

Modified: branches/safari-606-branch/LayoutTests/platform/ios/TestExpectations (239392 => 239393)


--- branches/safari-606-branch/LayoutTests/platform/ios/TestExpectations	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/LayoutTests/platform/ios/TestExpectations	2018-12-19 22:05:29 UTC (rev 239393)
@@ -2822,6 +2822,7 @@
 # LEGACY_ENCRYPTED_MEDIA is disabled on iOS.
 fast/events/webkit-media-key-events-constructor.html [ Failure ]
 
+http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html [ Pass ]
 webkit.org/b/161143 imported/w3c/web-platform-tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/scroll-restoration-fragment-scrolling-samedoc.html [ Pass Failure ]
 
 webkit.org/b/161395 svg/animations/reinserting-svg-into-document.html [ Pass Failure ]

Modified: branches/safari-606-branch/LayoutTests/platform/mac-wk2/TestExpectations (239392 => 239393)


--- branches/safari-606-branch/LayoutTests/platform/mac-wk2/TestExpectations	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/LayoutTests/platform/mac-wk2/TestExpectations	2018-12-19 22:05:29 UTC (rev 239393)
@@ -769,6 +769,7 @@
 webkit.org/b/172148 tiled-drawing/scrolling/scroll-snap/scroll-snap-mandatory-mainframe-vertical.html [ Pass Failure ]
 
 webkit.org/b/175341 accessibility/mac/select-element-selection-with-optgroups.html [ Pass Failure ]
+http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html [ Pass ]
 
 webkit.org/b/172044 [ Debug ] imported/w3c/web-platform-tests/IndexedDB/open-request-queue.html [ Pass Timeout ]
 

Modified: branches/safari-606-branch/Source/WebCore/ChangeLog (239392 => 239393)


--- branches/safari-606-branch/Source/WebCore/ChangeLog	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/Source/WebCore/ChangeLog	2018-12-19 22:05:29 UTC (rev 239393)
@@ -1,3 +1,52 @@
+2018-12-19  Kocsen Chung  <[email protected]>
+
+        Apply patch. rdar://problem/46848447
+
+    2018-12-19  John Wilander  <[email protected]>
+
+            Cap lifetime of persistent cookies created client-side through document.cookie
+            https://bugs.webkit.org/show_bug.cgi?id=189933
+            <rdar://problem/44741888>
+
+            Reviewed by Chris Dumez.
+
+            Test: http/tests/cookies/capped-lifetime-for-cookie-set-in-js.html
+
+            As pointed out in https://github.com/mikewest/http-state-tokens:
+
+            1) Cookies are available to _javascript_ by default via document.cookie, which
+            enables a smooth upgrade from one-time XSS to theft of persistent credentials
+            and also makes cookies available to Spectre-like attacks on memory.
+
+            2) Though the HttpOnly attribute was introduced well over a decade ago, only
+            ~8.31% of Set-Cookie operations use it today (stats from Chrome). We need
+            developer incentives to put proper protections in place.
+
+            3) The median (uncompressed) Cookie request header is 409 bytes, while the 90th
+            percentile is 1,589 bytes, the 95th 2,549 bytes, the 99th 4,601 bytes, and
+            ~0.1% of Cookie headers are over 10kB (stats from Chrome). This is bad for load
+            performance.
+
+            In addition to this, third-party scripts running in first-party contexts can
+            read user data through document.cookie and even store cross-site tracking data
+            in them.
+
+            Authentication cookies should be HttpOnly and thus not be affected by
+            restrictions to document.cookie. Cookies that persist for a long time should
+            be Secure, HttpOnly, and SameSite to provide good security and privacy.
+
+            By capping the lifetime of persistent cookies set through document.cookie we
+            embark on a journey towards better cookie management on the web.
+
+            * platform/network/cocoa/NetworkStorageSessionCocoa.mm:
+            (WebCore::filterCookies):
+                Now caps the life time of persistent cookies to one week (seven days).
+            * testing/Internals.cpp:
+            (WebCore::Internals::getCookies const):
+                New test function to get to cookie meta data such as expiry.
+            * testing/Internals.h:
+            * testing/Internals.idl:
+
 2018-12-14  Alan Coon  <[email protected]>
 
         Apply patch. rdar://problem/46603448

Modified: branches/safari-606-branch/Source/WebCore/PAL/pal/spi/cg/CoreGraphicsSPI.h (239392 => 239393)


--- branches/safari-606-branch/Source/WebCore/PAL/pal/spi/cg/CoreGraphicsSPI.h	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/Source/WebCore/PAL/pal/spi/cg/CoreGraphicsSPI.h	2018-12-19 22:05:29 UTC (rev 239393)
@@ -302,6 +302,14 @@
 size_t CGDisplayModeGetPixelsWide(CGDisplayModeRef);
 size_t CGDisplayModeGetPixelsHigh(CGDisplayModeRef);
 
+#if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+CGError CGSSetDenyWindowServerConnections(bool);
+
+typedef int32_t CGSDisplayID;
+CGSDisplayID CGSMainDisplayID(void);
+
+#endif // ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
+
 #endif
 
 WTF_EXTERN_C_END

Modified: branches/safari-606-branch/Source/WebCore/platform/network/mac/CookieJarMac.mm (239392 => 239393)


--- branches/safari-606-branch/Source/WebCore/platform/network/mac/CookieJarMac.mm	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/Source/WebCore/platform/network/mac/CookieJarMac.mm	2018-12-19 22:05:29 UTC (rev 239393)
@@ -151,6 +151,7 @@
     NSUInteger count = [unfilteredCookies count];
     RetainPtr<NSMutableArray> filteredCookies = adoptNS([[NSMutableArray alloc] initWithCapacity:count]);
 
+    const NSTimeInterval secondsPerWeek = 7 * 24 * 60 * 60;
     for (NSUInteger i = 0; i < count; ++i) {
         NSHTTPCookie *cookie = (NSHTTPCookie *)[unfilteredCookies objectAtIndex:i];
 
@@ -164,6 +165,16 @@
         if ([cookie isHTTPOnly])
             continue;
 
+        // Cap lifetime of persistent, client-side cookies to a week.
+        if (![cookie isSessionOnly]) {
+            if (!cookie.expiresDate || cookie.expiresDate.timeIntervalSinceNow > secondsPerWeek) {
+                RetainPtr<NSMutableDictionary<NSHTTPCookiePropertyKey, id>> properties = adoptNS([[cookie properties] mutableCopy]);
+                RetainPtr<NSDate> dateInAWeek = adoptNS([[NSDate alloc] initWithTimeIntervalSinceNow:secondsPerWeek]);
+                [properties setObject:dateInAWeek.get() forKey:NSHTTPCookieExpires];
+                cookie = [NSHTTPCookie cookieWithProperties:properties.get()];
+            }
+        }
+
         [filteredCookies.get() addObject:cookie];
     }
 

Modified: branches/safari-606-branch/Source/WebCore/testing/Internals.cpp (239392 => 239393)


--- branches/safari-606-branch/Source/WebCore/testing/Internals.cpp	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/Source/WebCore/testing/Internals.cpp	2018-12-19 22:05:29 UTC (rev 239393)
@@ -47,6 +47,7 @@
 #include "Chrome.h"
 #include "ClientOrigin.h"
 #include "ComposedTreeIterator.h"
+#include "CookieJar.h"
 #include "Cursor.h"
 #include "DOMRect.h"
 #include "DOMRectList.h"
@@ -4697,4 +4698,17 @@
     document->setAlwaysAllowLocalWebarchive();
 }
 
+auto Internals::getCookies() const -> Vector<CookieData>
+{
+    auto* document = contextDocument();
+    if (!document)
+        return { };
+
+    Vector<Cookie> cookies;
+    getRawCookies(*document, document->cookieURL(), cookies);
+    return WTF::map(cookies, [](auto& cookie) {
+        return CookieData { cookie };
+    });
+}
+
 } // namespace WebCore

Modified: branches/safari-606-branch/Source/WebCore/testing/Internals.h (239392 => 239393)


--- branches/safari-606-branch/Source/WebCore/testing/Internals.h	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/Source/WebCore/testing/Internals.h	2018-12-19 22:05:29 UTC (rev 239393)
@@ -28,6 +28,7 @@
 
 #include "CSSComputedStyleDeclaration.h"
 #include "ContextDestructionObserver.h"
+#include "Cookie.h"
 #include "ExceptionOr.h"
 #include "JSDOMPromiseDeferred.h"
 #include "OrientationNotifier.h"
@@ -727,6 +728,38 @@
 
     void setAlwaysAllowLocalWebarchive() const;
 
+    struct CookieData {
+        String name;
+        String value;
+        String domain;
+        // Expiration dates are expressed as milliseconds since the UNIX epoch.
+        double expires { 0 };
+        bool isHttpOnly { false };
+        bool isSecure { false };
+        bool isSession { false };
+        bool isSameSiteLax { false };
+        bool isSameSiteStrict { false };
+
+        CookieData(Cookie cookie)
+            : name(cookie.name)
+            , value(cookie.value)
+            , domain(cookie.domain)
+            , expires(cookie.expires)
+            , isHttpOnly(cookie.httpOnly)
+            , isSecure(cookie.secure)
+            , isSession(cookie.session)
+            , isSameSiteLax(cookie.sameSite == Cookie::SameSitePolicy::Lax)
+            , isSameSiteStrict(cookie.sameSite == Cookie::SameSitePolicy::Strict)
+        {
+            ASSERT(!(isSameSiteLax && isSameSiteStrict));
+        }
+
+        CookieData()
+        {
+        }
+    };
+    Vector<CookieData> getCookies() const;
+
 private:
     explicit Internals(Document&);
     Document* contextDocument() const;

Modified: branches/safari-606-branch/Source/WebCore/testing/Internals.idl (239392 => 239393)


--- branches/safari-606-branch/Source/WebCore/testing/Internals.idl	2018-12-19 22:00:43 UTC (rev 239392)
+++ branches/safari-606-branch/Source/WebCore/testing/Internals.idl	2018-12-19 22:05:29 UTC (rev 239393)
@@ -124,6 +124,21 @@
 
 [
     ExportMacro=WEBCORE_TESTSUPPORT_EXPORT,
+    JSGenerateToJSObject,
+] dictionary CookieData {
+    DOMString name;
+    DOMString value;
+    DOMString domain;
+    double expires;
+    boolean isHttpOnly;
+    boolean isSecure;
+    boolean isSession;
+    boolean isSameSiteLax;
+    boolean isSameSiteStrict;
+};
+
+[
+    ExportMacro=WEBCORE_TESTSUPPORT_EXPORT,
     NoInterfaceObject,
 ] interface Internals {
     DOMString address(Node node);
@@ -666,4 +681,6 @@
     void notifyResourceLoadObserver();
 
     void setAlwaysAllowLocalWebarchive();
+
+    sequence<CookieData> getCookies();
 };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to